blob: 0de335d8c72d8f058e3fa661af1f0ecebf66ffff [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 McCullochf3173222012-06-07 21:57:32 +00008import aQute.bnd.service.RepositoryPlugin.Strategy;
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
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 McCulloch4482c702012-06-15 13:27:53 +000021 volatile Map<String,String> attributes;
Stuart McCullochf3173222012-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 McCulloch4482c702012-06-15 13:27:53 +000026 Map<String,String> attributes) {
Stuart McCullochf3173222012-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 McCulloch4482c702012-06-15 13:27:53 +000060 case EXTERNAL :
61 case REPO :
62 files.add(file);
63 return true;
Stuart McCullochf3173222012-06-07 21:57:32 +000064
Stuart McCulloch4482c702012-06-15 13:27:53 +000065 case PROJECT :
66 File[] fs = project.build();
67 reporter.getInfo(project);
68 if (fs == null)
Stuart McCullochf3173222012-06-07 21:57:32 +000069 return false;
Stuart McCullochf3173222012-06-07 21:57:32 +000070
Stuart McCulloch4482c702012-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 McCullochf3173222012-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
Stuart McCulloch2929e2d2012-08-07 10:57:21 +0000106 @Override
Stuart McCullochf3173222012-06-07 21:57:32 +0000107 public boolean equals(Object other) {
108 if (other instanceof Container)
109 return file.equals(((Container) other).file);
Stuart McCulloch669423b2012-06-26 16:34:24 +0000110 return false;
Stuart McCullochf3173222012-06-07 21:57:32 +0000111 }
112
Stuart McCulloch2929e2d2012-08-07 10:57:21 +0000113 @Override
Stuart McCullochf3173222012-06-07 21:57:32 +0000114 public int hashCode() {
115 return file.hashCode();
116 }
117
118 public Project getProject() {
119 return project;
120 }
121
122 /**
123 * Must show the file name or the error formatted as a file name
124 *
125 * @return
126 */
Stuart McCulloch2929e2d2012-08-07 10:57:21 +0000127 @Override
Stuart McCullochf3173222012-06-07 21:57:32 +0000128 public String toString() {
129 if (getError() != null)
130 return "/error/" + getError();
Stuart McCulloch669423b2012-06-26 16:34:24 +0000131 return getFile().getAbsolutePath();
Stuart McCullochf3173222012-06-07 21:57:32 +0000132 }
133
Stuart McCulloch4482c702012-06-15 13:27:53 +0000134 public Map<String,String> getAttributes() {
Stuart McCullochf3173222012-06-07 21:57:32 +0000135 return attributes;
136 }
Stuart McCulloch4482c702012-06-15 13:27:53 +0000137
Stuart McCullochf3173222012-06-07 21:57:32 +0000138 public void putAttribute(String name, String value) {
Stuart McCulloch4482c702012-06-15 13:27:53 +0000139 if (attributes == Collections.<String, String> emptyMap())
140 attributes = new HashMap<String,String>(1);
Stuart McCullochf3173222012-06-07 21:57:32 +0000141 attributes.put(name, value);
142 }
143
144 /**
145 * Return the this if this is anything else but a library. If it is a
146 * library, return the members. This could work recursively, e.g., libraries
147 * can point to libraries.
148 *
149 * @return
150 * @throws Exception
151 */
152 public List<Container> getMembers() throws Exception {
153 List<Container> result = project.newList();
154
155 // Are ww a library? If no, we are the result
156 if (getType() == TYPE.LIBRARY) {
157 // We are a library, parse the file. This is
158 // basically a specification clause per line.
159 // I.e. you can do bsn; version, bsn2; version. But also
160 // spread it out over lines.
161 InputStream in = null;
162 BufferedReader rd = null;
163 String line;
164 try {
165 in = new FileInputStream(file);
Stuart McCulloch4482c702012-06-15 13:27:53 +0000166 rd = new BufferedReader(new InputStreamReader(in, Constants.DEFAULT_CHARSET));
Stuart McCullochf3173222012-06-07 21:57:32 +0000167 while ((line = rd.readLine()) != null) {
168 line = line.trim();
169 if (!line.startsWith("#") && line.length() > 0) {
170 List<Container> list = project.getBundles(Strategy.HIGHEST, line, null);
171 result.addAll(list);
172 }
173 }
Stuart McCulloch4482c702012-06-15 13:27:53 +0000174 }
175 finally {
Stuart McCullochf3173222012-06-07 21:57:32 +0000176 if (rd != null) {
177 rd.close();
178 }
179 if (in != null) {
180 in.close();
181 }
182 }
183 } else
184 result.add(this);
185
186 return result;
187 }
188
189 /**
190 * Answer the manifest for this container (if possible). Manifest is cached
191 * until the file is renewed.
192 */
193
194 public Manifest getManifest() throws Exception {
195 if (getError() != null || getFile() == null)
196 return null;
197
198 if (manifestTime < getFile().lastModified()) {
199 InputStream in = new FileInputStream(getFile());
200 try {
201 JarInputStream jin = new JarInputStream(in);
202 manifest = jin.getManifest();
203 jin.close();
204 manifestTime = getFile().lastModified();
Stuart McCulloch4482c702012-06-15 13:27:53 +0000205 }
206 finally {
Stuart McCullochf3173222012-06-07 21:57:32 +0000207 in.close();
208 }
209 }
210 return manifest;
211 }
212}