blob: ed8a94e2a0c8e9f8b6c527f44dae85e9b74fb7b8 [file] [log] [blame]
Stuart McCulloch26e7a5a2011-10-17 10:31:43 +00001package aQute.bnd.build;
2
3import java.io.*;
4import java.lang.ref.*;
5import java.util.*;
6import java.util.concurrent.*;
7import java.util.concurrent.locks.*;
8import java.util.jar.*;
9
10import javax.naming.*;
11
12import aQute.bnd.maven.support.*;
13import aQute.bnd.service.*;
14import aQute.bnd.service.action.*;
15import aQute.lib.deployer.*;
16import aQute.lib.io.*;
17import aQute.lib.osgi.*;
18
19public class Workspace extends Processor {
20 public static final String BUILDFILE = "build.bnd";
21 public static final String CNFDIR = "cnf";
22 public static final String BNDDIR = "bnd";
23 public static final String CACHEDIR = "cache";
24
25 static Map<File, WeakReference<Workspace>> cache = newHashMap();
26 final Map<String, Project> models = newHashMap();
27 final Map<String, Action> commands = newMap();
28 final CachedFileRepo cachedRepo;
29 final File buildDir;
30 final Maven maven = new Maven(Processor.getExecutor());
31 private boolean postpone;
32
33 /**
34 * This static method finds the workspace and creates a project (or returns
35 * an existing project)
36 *
37 * @param projectDir
38 * @return
39 */
40 public static Project getProject(File projectDir) throws Exception {
41 projectDir = projectDir.getAbsoluteFile();
42 assert projectDir.isDirectory();
43
44 Workspace ws = getWorkspace(projectDir.getParentFile());
45 return ws.getProject(projectDir.getName());
46 }
47
48 public static Workspace getWorkspace(File parent) throws Exception {
49 File workspaceDir = parent.getAbsoluteFile();
50
51 // the cnf directory can actually be a
52 // file that redirects
53 while (workspaceDir.isDirectory()) {
54 File test = new File(workspaceDir, CNFDIR);
55
56 if (!test.exists())
57 test = new File(workspaceDir, BNDDIR);
58
59 if (test.isDirectory())
60 break;
61
62 if (test.isFile()) {
63 String redirect = IO.collect(test).trim();
64 test = getFile(test.getParentFile(), redirect).getAbsoluteFile();
65 workspaceDir = test;
66 }
67 if (!test.exists())
68 throw new IllegalArgumentException("No Workspace found from: " + parent);
69 }
70
71 synchronized (cache) {
72 WeakReference<Workspace> wsr = cache.get(workspaceDir);
73 Workspace ws;
74 if (wsr == null || (ws = wsr.get()) == null) {
75 ws = new Workspace(workspaceDir);
76 cache.put(workspaceDir, new WeakReference<Workspace>(ws));
77 }
78 return ws;
79 }
80 }
81
82 public Workspace(File dir) throws Exception {
83 dir = dir.getAbsoluteFile();
84 dir.mkdirs();
85 assert dir.isDirectory();
86
87 File buildDir = new File(dir, BNDDIR).getAbsoluteFile();
88 if (!buildDir.isDirectory())
89 buildDir = new File(dir, CNFDIR).getAbsoluteFile();
90
91 this.buildDir = buildDir;
92
93 File buildFile = new File(buildDir, BUILDFILE).getAbsoluteFile();
94 if (!buildFile.isFile())
95 warning("No Build File in " + dir);
96
97 setProperties(buildFile, dir);
98 propertiesChanged();
99
100 cachedRepo = new CachedFileRepo();
101 }
102
103 public Project getProject(String bsn) throws Exception {
104 synchronized (models) {
105 Project project = models.get(bsn);
106 if (project != null)
107 return project;
108
109 File projectDir = getFile(bsn);
110 project = new Project(this, projectDir);
111 if (!project.isValid())
112 return null;
113
114 models.put(bsn, project);
115 return project;
116 }
117 }
118
119 public boolean isPresent(String name) {
120 return models.containsKey(name);
121 }
122
123 public Collection<Project> getCurrentProjects() {
124 return models.values();
125 }
126
127 public boolean refresh() {
128 if (super.refresh()) {
129 for (Project project : getCurrentProjects()) {
130 project.propertiesChanged();
131 }
132 return true;
133 }
134 return false;
135 }
136
137 @Override
138 public void propertiesChanged() {
139 super.propertiesChanged();
140 File extDir = new File(this.buildDir, "ext");
141 File[] extensions = extDir.listFiles();
142 if (extensions != null) {
143 for (File extension : extensions) {
144 if (extension.getName().endsWith(".bnd")) {
145 try {
146 doIncludeFile(extension, true, getProperties());
147 } catch (Exception e) {
148 error("PropertiesChanged: " + e.getMessage());
149 }
150 }
151 }
152 }
153 }
154
155 public String _workspace(String args[]) {
156 return getBase().getAbsolutePath();
157 }
158
159 public void addCommand(String menu, Action action) {
160 commands.put(menu, action);
161 }
162
163 public void removeCommand(String menu) {
164 commands.remove(menu);
165 }
166
167 public void fillActions(Map<String, Action> all) {
168 all.putAll(commands);
169 }
170
171 public Collection<Project> getAllProjects() throws Exception {
172 List<Project> projects = new ArrayList<Project>();
173 for (File file : getBase().listFiles()) {
174 if (new File(file, Project.BNDFILE).isFile())
175 projects.add(getProject(file));
176 }
177 return projects;
178 }
179
180 /**
181 * Inform any listeners that we changed a file (created/deleted/changed).
182 *
183 * @param f
184 * The changed file
185 */
186 public void changedFile(File f) {
187 List<BndListener> listeners = getPlugins(BndListener.class);
188 for (BndListener l : listeners)
189 try {
190 l.changed(f);
191 } catch (Exception e) {
192 e.printStackTrace();
193 }
194 }
195
196 public void bracket(boolean begin) {
197 List<BndListener> listeners = getPlugins(BndListener.class);
198 for (BndListener l : listeners)
199 try {
200 if ( begin )
201 l.begin();
202 else
203 l.end();
204 } catch (Exception e) {
205 // who cares?
206 }
207 }
208
209
210 private void copy(InputStream in, OutputStream out) throws Exception {
211 byte data[] = new byte[10000];
212 int size = in.read(data);
213 while (size > 0) {
214 out.write(data, 0, size);
215 size = in.read(data);
216 }
217 }
218
219 class CachedFileRepo extends FileRepo {
220 final Lock lock = new ReentrantLock();
221 boolean inited;
222
223 CachedFileRepo() {
224 super("cache", getFile(buildDir, CACHEDIR), false);
225 }
226
227 protected void init() throws Exception {
228 if (lock.tryLock(50, TimeUnit.SECONDS) == false)
229 throw new TimeLimitExceededException(
230 "Cached File Repo is locked and can't acquire it");
231 try {
232 if (!inited) {
233 inited = true;
234 root.mkdirs();
235 if (!root.isDirectory())
236 throw new IllegalArgumentException("Cannot create cache dir " + root);
237
238 InputStream in = getClass().getResourceAsStream(EMBEDDED_REPO);
239 if (in != null)
240 unzip(in, root);
241 else
242 System.out.println("!!!! WTF Couldn't find embedded-repo.jar in bundle ");
243 }
244 } finally {
245 lock.unlock();
246 }
247 }
248
249 void unzip(InputStream in, File dir) throws Exception {
250 try {
251 JarInputStream jin = new JarInputStream(in);
252 JarEntry jentry = jin.getNextJarEntry();
253 while (jentry != null) {
254 if (!jentry.isDirectory()) {
255 File dest = Processor.getFile(dir, jentry.getName());
256 if (!dest.isFile() || dest.lastModified() < jentry.getTime()
257 || jentry.getTime() == 0) {
258 dest.getParentFile().mkdirs();
259 FileOutputStream out = new FileOutputStream(dest);
260 try {
261 copy(jin, out);
262 } finally {
263 out.close();
264 }
265 }
266 }
267 jentry = jin.getNextJarEntry();
268 }
269 } finally {
270 in.close();
271 }
272 }
273 }
274
275 public List<RepositoryPlugin> getRepositories() {
276 return getPlugins(RepositoryPlugin.class);
277 }
278
279 public static Workspace getWorkspace(String path) throws Exception {
280 File file = IO.getFile(new File(""), path);
281 return getWorkspace(file);
282 }
283
284 public Maven getMaven() {
285 return maven;
286 }
287
288 @Override
289 protected void setTypeSpecificPlugins( Set<Object> list) {
290 super.setTypeSpecificPlugins(list);
291 list.add(maven);
292 list.add(cachedRepo);
293 }
294}