blob: 8a721c98ee1cf619de1141ee6ee0b999560df85c [file] [log] [blame]
Stuart McCullochbb014372012-06-07 21:57:32 +00001package aQute.bnd.build;
2
3import java.io.*;
4import java.util.*;
5import java.util.jar.*;
6
Stuart McCulloch39cc9ac2012-07-16 13:43:38 +00007import aQute.bnd.osgi.*;
Stuart McCullochbb014372012-06-07 21:57:32 +00008import aQute.bnd.service.RepositoryPlugin.Strategy;
Stuart McCullochbb014372012-06-07 21:57:32 +00009
10public class Container {
11 public enum TYPE {
Stuart McCulloch151384c2012-06-18 11:15:15 +000012 REPO, PROJECT, EXTERNAL, LIBRARY, ERROR
Stuart McCullochbb014372012-06-07 21:57:32 +000013 }
14
15 final File file;
16 final TYPE type;
17 final String bsn;
18 final String version;
19 final String error;
20 final Project project;
Stuart McCulloch2286f232012-06-15 13:27:53 +000021 volatile Map<String,String> attributes;
Stuart McCullochbb014372012-06-07 21:57:32 +000022 private long manifestTime;
23 private Manifest manifest;
24
25 Container(Project project, String bsn, String version, TYPE type, File source, String error,
Stuart McCulloch2286f232012-06-15 13:27:53 +000026 Map<String,String> attributes) {
Stuart McCullochbb014372012-06-07 21:57:32 +000027 this.bsn = bsn;
28 this.version = version;
29 this.type = type;
30 this.file = source != null ? source : new File("/" + bsn + ":" + version + ":" + type);
31 this.project = project;
32 this.error = error;
33 if (attributes == null || attributes.isEmpty())
34 this.attributes = Collections.emptyMap();
35 else
36 this.attributes = attributes;
37 }
38
39 public Container(Project project, File file) {
40 this(project, file.getName(), "project", TYPE.PROJECT, file, null, null);
41 }
42
43 public Container(File file) {
44 this(null, file.getName(), "project", TYPE.EXTERNAL, file, null, null);
45 }
46
47 public File getFile() {
48 return file;
49 }
50
51 /**
52 * Iterate over the containers and get the files they represent
53 *
54 * @param files
55 * @return
56 * @throws Exception
57 */
58 public boolean contributeFiles(List<File> files, Processor reporter) throws Exception {
59 switch (type) {
Stuart McCulloch2286f232012-06-15 13:27:53 +000060 case EXTERNAL :
61 case REPO :
62 files.add(file);
63 return true;
Stuart McCullochbb014372012-06-07 21:57:32 +000064
Stuart McCulloch2286f232012-06-15 13:27:53 +000065 case PROJECT :
66 File[] fs = project.build();
67 reporter.getInfo(project);
68 if (fs == null)
Stuart McCullochbb014372012-06-07 21:57:32 +000069 return false;
Stuart McCullochbb014372012-06-07 21:57:32 +000070
Stuart McCulloch2286f232012-06-15 13:27:53 +000071 for (File f : fs)
72 files.add(f);
73 return true;
74
75 case LIBRARY :
76 List<Container> containers = getMembers();
77 for (Container container : containers) {
78 if (!container.contributeFiles(files, reporter))
79 return false;
80 }
81 return true;
82
83 case ERROR :
84 reporter.error(error);
85 return false;
Stuart McCullochbb014372012-06-07 21:57:32 +000086 }
87 return false;
88 }
89
90 public String getBundleSymbolicName() {
91 return bsn;
92 }
93
94 public String getVersion() {
95 return version;
96 }
97
98 public TYPE getType() {
99 return type;
100 }
101
102 public String getError() {
103 return error;
104 }
105
106 public boolean equals(Object other) {
107 if (other instanceof Container)
108 return file.equals(((Container) other).file);
Stuart McCullochd4826102012-06-26 16:34:24 +0000109 return false;
Stuart McCullochbb014372012-06-07 21:57:32 +0000110 }
111
112 public int hashCode() {
113 return file.hashCode();
114 }
115
116 public Project getProject() {
117 return project;
118 }
119
120 /**
121 * Must show the file name or the error formatted as a file name
122 *
123 * @return
124 */
125 public String toString() {
126 if (getError() != null)
127 return "/error/" + getError();
Stuart McCullochd4826102012-06-26 16:34:24 +0000128 return getFile().getAbsolutePath();
Stuart McCullochbb014372012-06-07 21:57:32 +0000129 }
130
Stuart McCulloch2286f232012-06-15 13:27:53 +0000131 public Map<String,String> getAttributes() {
Stuart McCullochbb014372012-06-07 21:57:32 +0000132 return attributes;
133 }
Stuart McCulloch2286f232012-06-15 13:27:53 +0000134
Stuart McCullochbb014372012-06-07 21:57:32 +0000135 public void putAttribute(String name, String value) {
Stuart McCulloch2286f232012-06-15 13:27:53 +0000136 if (attributes == Collections.<String, String> emptyMap())
137 attributes = new HashMap<String,String>(1);
Stuart McCullochbb014372012-06-07 21:57:32 +0000138 attributes.put(name, value);
139 }
140
141 /**
142 * Return the this if this is anything else but a library. If it is a
143 * library, return the members. This could work recursively, e.g., libraries
144 * can point to libraries.
145 *
146 * @return
147 * @throws Exception
148 */
149 public List<Container> getMembers() throws Exception {
150 List<Container> result = project.newList();
151
152 // Are ww a library? If no, we are the result
153 if (getType() == TYPE.LIBRARY) {
154 // We are a library, parse the file. This is
155 // basically a specification clause per line.
156 // I.e. you can do bsn; version, bsn2; version. But also
157 // spread it out over lines.
158 InputStream in = null;
159 BufferedReader rd = null;
160 String line;
161 try {
162 in = new FileInputStream(file);
Stuart McCulloch2286f232012-06-15 13:27:53 +0000163 rd = new BufferedReader(new InputStreamReader(in, Constants.DEFAULT_CHARSET));
Stuart McCullochbb014372012-06-07 21:57:32 +0000164 while ((line = rd.readLine()) != null) {
165 line = line.trim();
166 if (!line.startsWith("#") && line.length() > 0) {
167 List<Container> list = project.getBundles(Strategy.HIGHEST, line, null);
168 result.addAll(list);
169 }
170 }
Stuart McCulloch2286f232012-06-15 13:27:53 +0000171 }
172 finally {
Stuart McCullochbb014372012-06-07 21:57:32 +0000173 if (rd != null) {
174 rd.close();
175 }
176 if (in != null) {
177 in.close();
178 }
179 }
180 } else
181 result.add(this);
182
183 return result;
184 }
185
186 /**
187 * Answer the manifest for this container (if possible). Manifest is cached
188 * until the file is renewed.
189 */
190
191 public Manifest getManifest() throws Exception {
192 if (getError() != null || getFile() == null)
193 return null;
194
195 if (manifestTime < getFile().lastModified()) {
196 InputStream in = new FileInputStream(getFile());
197 try {
198 JarInputStream jin = new JarInputStream(in);
199 manifest = jin.getManifest();
200 jin.close();
201 manifestTime = getFile().lastModified();
Stuart McCulloch2286f232012-06-15 13:27:53 +0000202 }
203 finally {
Stuart McCullochbb014372012-06-07 21:57:32 +0000204 in.close();
205 }
206 }
207 return manifest;
208 }
209}