blob: f693ddb6774f9b9b581ae45e8872d39189eee3dc [file] [log] [blame]
Stuart McCullochf3173222012-06-07 21:57:32 +00001package aQute.bnd.build;
2
3import java.io.*;
4import java.util.*;
5import java.util.jar.*;
6
Stuart McCulloch42151ee2012-07-16 13:43:38 +00007import aQute.bnd.osgi.*;
Stuart McCulloch2a0afd62012-09-06 18:28:06 +00008import aQute.bnd.service.*;
Stuart McCullochf3173222012-06-07 21:57:32 +00009
10public class Container {
11 public enum TYPE {
Stuart McCulloch1b98aa02012-06-18 11:15:15 +000012 REPO, PROJECT, EXTERNAL, LIBRARY, ERROR
Stuart McCullochf3173222012-06-07 21:57:32 +000013 }
14
Stuart McCulloch2a0afd62012-09-06 18:28:06 +000015 private final File file;
16 private final String path;
Stuart McCullochf3173222012-06-07 21:57:32 +000017 final TYPE type;
18 final String bsn;
19 final String version;
20 final String error;
21 final Project project;
Stuart McCulloch2a0afd62012-09-06 18:28:06 +000022 final DownloadBlocker db;
Stuart McCulloch4482c702012-06-15 13:27:53 +000023 volatile Map<String,String> attributes;
Stuart McCullochf3173222012-06-07 21:57:32 +000024 private long manifestTime;
25 private Manifest manifest;
26
27 Container(Project project, String bsn, String version, TYPE type, File source, String error,
Stuart McCulloch2a0afd62012-09-06 18:28:06 +000028 Map<String,String> attributes, DownloadBlocker db) {
Stuart McCullochf3173222012-06-07 21:57:32 +000029 this.bsn = bsn;
30 this.version = version;
31 this.type = type;
32 this.file = source != null ? source : new File("/" + bsn + ":" + version + ":" + type);
Stuart McCulloch2a0afd62012-09-06 18:28:06 +000033 this.path = file.getAbsolutePath();
34
Stuart McCullochf3173222012-06-07 21:57:32 +000035 this.project = project;
36 this.error = error;
37 if (attributes == null || attributes.isEmpty())
38 this.attributes = Collections.emptyMap();
39 else
40 this.attributes = attributes;
Stuart McCulloch2a0afd62012-09-06 18:28:06 +000041 this.db = db;
Stuart McCullochf3173222012-06-07 21:57:32 +000042 }
43
44 public Container(Project project, File file) {
Stuart McCulloch2a0afd62012-09-06 18:28:06 +000045 this(project, file.getName(), "project", TYPE.PROJECT, file, null, null, null);
Stuart McCullochf3173222012-06-07 21:57:32 +000046 }
47
Stuart McCulloch2a0afd62012-09-06 18:28:06 +000048 public Container(File file, DownloadBlocker db) {
49 this(null, file.getName(), "project", TYPE.EXTERNAL, file, null, null, db);
Stuart McCullochf3173222012-06-07 21:57:32 +000050 }
51
52 public File getFile() {
Stuart McCulloch2a0afd62012-09-06 18:28:06 +000053 if (db != null && db.getReason() != null) {
54 return new File(db.getReason() + ": " + file);
55 }
Stuart McCullochf3173222012-06-07 21:57:32 +000056 return file;
57 }
58
59 /**
60 * Iterate over the containers and get the files they represent
61 *
62 * @param files
63 * @return
64 * @throws Exception
65 */
66 public boolean contributeFiles(List<File> files, Processor reporter) throws Exception {
67 switch (type) {
Stuart McCulloch4482c702012-06-15 13:27:53 +000068 case EXTERNAL :
69 case REPO :
Stuart McCulloch2a0afd62012-09-06 18:28:06 +000070 files.add(getFile());
Stuart McCulloch4482c702012-06-15 13:27:53 +000071 return true;
Stuart McCullochf3173222012-06-07 21:57:32 +000072
Stuart McCulloch4482c702012-06-15 13:27:53 +000073 case PROJECT :
74 File[] fs = project.build();
75 reporter.getInfo(project);
76 if (fs == null)
Stuart McCullochf3173222012-06-07 21:57:32 +000077 return false;
Stuart McCullochf3173222012-06-07 21:57:32 +000078
Stuart McCulloch4482c702012-06-15 13:27:53 +000079 for (File f : fs)
80 files.add(f);
81 return true;
82
83 case LIBRARY :
84 List<Container> containers = getMembers();
85 for (Container container : containers) {
86 if (!container.contributeFiles(files, reporter))
87 return false;
88 }
89 return true;
90
91 case ERROR :
92 reporter.error(error);
93 return false;
Stuart McCullochf3173222012-06-07 21:57:32 +000094 }
95 return false;
96 }
97
98 public String getBundleSymbolicName() {
99 return bsn;
100 }
101
102 public String getVersion() {
103 return version;
104 }
105
106 public TYPE getType() {
107 return type;
108 }
109
110 public String getError() {
111 return error;
112 }
113
Stuart McCulloch2929e2d2012-08-07 10:57:21 +0000114 @Override
Stuart McCullochf3173222012-06-07 21:57:32 +0000115 public boolean equals(Object other) {
116 if (other instanceof Container)
Stuart McCulloch2a0afd62012-09-06 18:28:06 +0000117 return path.equals(((Container) other).path);
Stuart McCulloch669423b2012-06-26 16:34:24 +0000118 return false;
Stuart McCullochf3173222012-06-07 21:57:32 +0000119 }
120
Stuart McCulloch2929e2d2012-08-07 10:57:21 +0000121 @Override
Stuart McCullochf3173222012-06-07 21:57:32 +0000122 public int hashCode() {
Stuart McCulloch2a0afd62012-09-06 18:28:06 +0000123 return path.hashCode();
Stuart McCullochf3173222012-06-07 21:57:32 +0000124 }
125
126 public Project getProject() {
127 return project;
128 }
129
130 /**
131 * Must show the file name or the error formatted as a file name
132 *
133 * @return
134 */
Stuart McCulloch2929e2d2012-08-07 10:57:21 +0000135 @Override
Stuart McCullochf3173222012-06-07 21:57:32 +0000136 public String toString() {
137 if (getError() != null)
138 return "/error/" + getError();
Stuart McCulloch669423b2012-06-26 16:34:24 +0000139 return getFile().getAbsolutePath();
Stuart McCullochf3173222012-06-07 21:57:32 +0000140 }
141
Stuart McCulloch4482c702012-06-15 13:27:53 +0000142 public Map<String,String> getAttributes() {
Stuart McCullochf3173222012-06-07 21:57:32 +0000143 return attributes;
144 }
Stuart McCulloch4482c702012-06-15 13:27:53 +0000145
Stuart McCullochf3173222012-06-07 21:57:32 +0000146 public void putAttribute(String name, String value) {
Stuart McCulloch4482c702012-06-15 13:27:53 +0000147 if (attributes == Collections.<String, String> emptyMap())
148 attributes = new HashMap<String,String>(1);
Stuart McCullochf3173222012-06-07 21:57:32 +0000149 attributes.put(name, value);
150 }
151
152 /**
153 * Return the this if this is anything else but a library. If it is a
154 * library, return the members. This could work recursively, e.g., libraries
155 * can point to libraries.
156 *
157 * @return
158 * @throws Exception
159 */
160 public List<Container> getMembers() throws Exception {
161 List<Container> result = project.newList();
162
163 // Are ww a library? If no, we are the result
164 if (getType() == TYPE.LIBRARY) {
165 // We are a library, parse the file. This is
166 // basically a specification clause per line.
167 // I.e. you can do bsn; version, bsn2; version. But also
168 // spread it out over lines.
169 InputStream in = null;
170 BufferedReader rd = null;
171 String line;
172 try {
Stuart McCulloch2a0afd62012-09-06 18:28:06 +0000173 in = new FileInputStream(getFile());
Stuart McCulloch4482c702012-06-15 13:27:53 +0000174 rd = new BufferedReader(new InputStreamReader(in, Constants.DEFAULT_CHARSET));
Stuart McCullochf3173222012-06-07 21:57:32 +0000175 while ((line = rd.readLine()) != null) {
176 line = line.trim();
177 if (!line.startsWith("#") && line.length() > 0) {
178 List<Container> list = project.getBundles(Strategy.HIGHEST, line, null);
179 result.addAll(list);
180 }
181 }
Stuart McCulloch4482c702012-06-15 13:27:53 +0000182 }
183 finally {
Stuart McCullochf3173222012-06-07 21:57:32 +0000184 if (rd != null) {
185 rd.close();
186 }
187 if (in != null) {
188 in.close();
189 }
190 }
191 } else
192 result.add(this);
193
194 return result;
195 }
196
197 /**
198 * Answer the manifest for this container (if possible). Manifest is cached
199 * until the file is renewed.
200 */
201
202 public Manifest getManifest() throws Exception {
203 if (getError() != null || getFile() == null)
204 return null;
205
206 if (manifestTime < getFile().lastModified()) {
207 InputStream in = new FileInputStream(getFile());
208 try {
209 JarInputStream jin = new JarInputStream(in);
210 manifest = jin.getManifest();
211 jin.close();
212 manifestTime = getFile().lastModified();
Stuart McCulloch4482c702012-06-15 13:27:53 +0000213 }
214 finally {
Stuart McCullochf3173222012-06-07 21:57:32 +0000215 in.close();
216 }
217 }
218 return manifest;
219 }
220}