Added
Link Here
|
1 |
/* |
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 |
* |
4 |
* Copyright 2009 Sun Microsystems, Inc. All rights reserved. |
5 |
* |
6 |
* The contents of this file are subject to the terms of either the GNU |
7 |
* General Public License Version 2 only ("GPL") or the Common |
8 |
* Development and Distribution License("CDDL") (collectively, the |
9 |
* "License"). You may not use this file except in compliance with the |
10 |
* License. You can obtain a copy of the License at |
11 |
* http://www.netbeans.org/cddl-gplv2.html |
12 |
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the |
13 |
* specific language governing permissions and limitations under the |
14 |
* License. When distributing the software, include this License Header |
15 |
* Notice in each file and include the License file at |
16 |
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this |
17 |
* particular file as subject to the "Classpath" exception as provided |
18 |
* by Sun in the GPL Version 2 section of the License file that |
19 |
* accompanied this code. If applicable, add the following below the |
20 |
* License Header, with the fields enclosed by brackets [] replaced by |
21 |
* your own identifying information: |
22 |
* "Portions Copyrighted [year] [name of copyright owner]" |
23 |
* |
24 |
* If you wish your version of this file to be governed by only the CDDL |
25 |
* or only the GPL Version 2, indicate your decision by adding |
26 |
* "[Contributor] elects to include this software in this distribution |
27 |
* under the [CDDL or GPL Version 2] license." If you do not indicate a |
28 |
* single choice of license, a recipient has the option to distribute |
29 |
* your version of this file under either the CDDL, the GPL Version 2 or |
30 |
* to extend the choice of license to its licensees as provided above. |
31 |
* However, if you add GPL Version 2 code and therefore, elected the GPL |
32 |
* Version 2 license, then the option applies only if the new code is |
33 |
* made subject to such option by the copyright holder. |
34 |
* |
35 |
* Contributor(s): |
36 |
* |
37 |
* Portions Copyrighted 2009 Sun Microsystems, Inc. |
38 |
*/ |
39 |
package org.netbeans.api.autoupdate; |
40 |
|
41 |
import java.io.File; |
42 |
import java.io.FileInputStream; |
43 |
import java.io.FileNotFoundException; |
44 |
import java.io.FileOutputStream; |
45 |
import java.io.IOException; |
46 |
import java.io.InputStream; |
47 |
import java.io.OutputStream; |
48 |
import java.io.OutputStreamWriter; |
49 |
import java.io.PrintWriter; |
50 |
import java.net.URL; |
51 |
import java.util.ArrayList; |
52 |
import java.util.List; |
53 |
import java.util.Set; |
54 |
import java.util.jar.Attributes; |
55 |
import java.util.jar.JarOutputStream; |
56 |
import java.util.jar.Manifest; |
57 |
import java.util.zip.ZipEntry; |
58 |
import org.netbeans.api.autoupdate.OperationContainer.OperationInfo; |
59 |
import org.netbeans.api.autoupdate.OperationSupport.Restarter; |
60 |
import org.netbeans.core.startup.MainLookup; |
61 |
import org.netbeans.junit.NbTestCase; |
62 |
import org.netbeans.modules.autoupdate.services.UpdateManagerImpl; |
63 |
import org.netbeans.modules.autoupdate.updateprovider.AutoupdateCatalogProvider; |
64 |
import org.openide.filesystems.FileUtil; |
65 |
import org.openide.util.Lookup; |
66 |
|
67 |
/** |
68 |
* |
69 |
* @author dlm198383 |
70 |
*/ |
71 |
public class InternalUpdatesTest extends NbTestCase { |
72 |
|
73 |
protected List<UpdateUnit> keepItNotToGC; |
74 |
private static File catalogFile; |
75 |
private static URL catalogURL; |
76 |
private File tmpDirectory; |
77 |
private List<File> nbms = new ArrayList<File>(); |
78 |
private List<String> moduleElements = new ArrayList<String>(); |
79 |
|
80 |
public InternalUpdatesTest(String testName) { |
81 |
super(testName); |
82 |
} |
83 |
|
84 |
public static class MyProvider extends AutoupdateCatalogProvider { |
85 |
|
86 |
public MyProvider() { |
87 |
super("test-updates-provider", "test-updates-provider", catalogURL, UpdateUnitProvider.CATEGORY.STANDARD); |
88 |
} |
89 |
} |
90 |
|
91 |
private String getModuleElement(boolean visible, String codeName, String moduleName, String distr, String specVersion, String dependency) { |
92 |
return "\n<module " + |
93 |
"\n codenamebase='" + codeName + "' " + |
94 |
"\n distribution='" + distr + "' " + |
95 |
"\n downloadsize='0' " + |
96 |
"\n homepage='' " + |
97 |
"\n license='AD9FBBC9' " + |
98 |
"\n moduleauthor='' " + |
99 |
"\n needsrestart='false' " + |
100 |
"\n releasedate='2007/01/30'>" + |
101 |
"\n <manifest " + |
102 |
"\n AutoUpdate-Show-In-Client='" + visible + "' " + |
103 |
"\n OpenIDE-Module='" + codeName + "' " + |
104 |
"\n OpenIDE-Module-Implementation-Version='070130' " + |
105 |
"\n OpenIDE-Module-Java-Dependencies='Java > 1.4' " + |
106 |
"\n OpenIDE-Module-Name='" + moduleName + "' " + |
107 |
(dependency != null ? " OpenIDE-Module-Module-Dependencies=\"" + dependency.replace(">", ">") + "\" " : "") + |
108 |
"\n OpenIDE-Module-Requires='org.openide.modules.ModuleFormat1' " + |
109 |
"\n OpenIDE-Module-Specification-Version='" + specVersion + "'/>" + |
110 |
"\n <license name='AD9FBBC9'>[NO LICENSE SPECIFIED]" + |
111 |
"\n</license>" + |
112 |
"\n</module>\n"; |
113 |
} |
114 |
|
115 |
private String createInfoXML(boolean visible, String codeName, String moduleName, String distr, String specVersion, String dependency) { |
116 |
String moduleElement = getModuleElement(visible, codeName, moduleName, distr, specVersion, dependency); |
117 |
|
118 |
moduleElements.add(moduleElement); |
119 |
return "<?xml version='1.0' encoding='UTF-8'?>" + |
120 |
"<!DOCTYPE module PUBLIC '-//NetBeans//DTD Autoupdate Module Info 2.5//EN' 'http://www.netbeans.org/dtds/autoupdate-info-2_5.dtd'>" + |
121 |
moduleElement; |
122 |
} |
123 |
|
124 |
private void writeCatalog() throws IOException { |
125 |
String res = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + |
126 |
"<!DOCTYPE module_updates PUBLIC \"-//NetBeans//DTD Autoupdate Catalog 2.5//EN\" \"http://www.netbeans.org/dtds/autoupdate-catalog-2_5.dtd\">" + |
127 |
"<module_updates timestamp=\"00/00/19/08/03/2006\">\n"; |
128 |
for (String element : moduleElements) { |
129 |
res += element; |
130 |
} |
131 |
res += "</module_updates>\n"; |
132 |
if (catalogFile == null) { |
133 |
catalogFile = File.createTempFile("catalog-", ".xml", tmpDirectory); |
134 |
catalogURL = catalogFile.toURI().toURL(); |
135 |
} |
136 |
PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(catalogFile), "UTF-8")); |
137 |
pw.write(res); |
138 |
pw.close(); |
139 |
} |
140 |
|
141 |
private String getConfigXML(String codeName, String moduleFile, String specVersion) { |
142 |
return "<?xml version='1.0' encoding='UTF-8'?>" + |
143 |
" <!DOCTYPE module PUBLIC '-//NetBeans//DTD Module Status 1.0//EN'" + |
144 |
" 'http://www.netbeans.org/dtds/module-status-1_0.dtd'>" + |
145 |
" <module name='" + codeName + "'>" + |
146 |
" <param name='autoload'>false</param>" + |
147 |
" <param name='eager'>false</param>" + |
148 |
" <param name='enabled'>true</param>" + |
149 |
" <param name='jar'>modules/" + moduleFile + ".jar</param>" + |
150 |
" <param name='reloadable'>false</param>" + |
151 |
" <param name='specversion'>" + specVersion + "</param>" + |
152 |
" </module>"; |
153 |
} |
154 |
|
155 |
private String getManifest(String codeName, String moduleDir, String specVersion, boolean visible, String dependency) { |
156 |
return "Manifest-Version: 1.0\n" + |
157 |
"Ant-Version: Apache Ant 1.7.0\n" + |
158 |
"Created-By: 1.6.0-b105 (Sun Microsystems Inc.)\n" + |
159 |
"OpenIDE-Module-Public-Packages: -\n" + |
160 |
"OpenIDE-Module-Java-Dependencies: Java > 1.4\n" + |
161 |
"OpenIDE-Module-Implementation-Version: 070130\n" + |
162 |
(dependency != null ? ("OpenIDE-Module-Module-Dependencies: " + dependency + "\n") : "") + |
163 |
"OpenIDE-Module: " + codeName + "\n" + |
164 |
"OpenIDE-Module-Localizing-Bundle: " + moduleDir + "Bundle.properties\n" + |
165 |
"OpenIDE-Module-Specification-Version: " + specVersion + "\n" + |
166 |
"OpenIDE-Module-Requires: org.openide.modules.ModuleFormat1\n" + |
167 |
"AutoUpdate-Show-In-Client: " + visible + "\n" + |
168 |
"\n"; |
169 |
} |
170 |
|
171 |
private File prepareNBM(String codeName, String specVersion, boolean visible, String dependency) throws Exception { |
172 |
String moduleName = codeName.substring(codeName.lastIndexOf(".") + 1); |
173 |
String moduleFile = codeName.replace(".", "-"); |
174 |
String moduleDir = codeName.replace(".", "/") + "/"; |
175 |
File nbm = File.createTempFile(moduleFile + "-", ".nbm", tmpDirectory); |
176 |
|
177 |
final String MODULE_NAME_PROP = "OpenIDE-Module-Name"; |
178 |
|
179 |
File jar = new File(tmpDirectory, "netbeans/modules/" + moduleFile + ".jar"); |
180 |
jar.getParentFile().mkdirs(); |
181 |
JarOutputStream jos = new JarOutputStream(new FileOutputStream(jar)); |
182 |
int idx = moduleDir.indexOf("/"); |
183 |
while (idx != -1) { |
184 |
jos.putNextEntry(new ZipEntry(moduleDir.substring(0, idx + 1))); |
185 |
idx = moduleDir.indexOf("/", idx + 1); |
186 |
} |
187 |
|
188 |
jos.putNextEntry(new ZipEntry(moduleDir + "Bundle.properties")); |
189 |
jos.write(new String(MODULE_NAME_PROP + "=" + moduleName).getBytes("UTF-8")); |
190 |
jos.putNextEntry(new ZipEntry("META-INF/")); |
191 |
jos.putNextEntry(new ZipEntry("META-INF/manifest.mf")); |
192 |
jos.write(getManifest(codeName, moduleDir, specVersion, visible, dependency).getBytes("UTF-8")); |
193 |
jos.close(); |
194 |
|
195 |
Manifest mf = new Manifest(); |
196 |
mf.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); |
197 |
jos = new JarOutputStream(new FileOutputStream(nbm), mf); |
198 |
jos.putNextEntry(new ZipEntry("Info/")); |
199 |
jos.putNextEntry(new ZipEntry("Info/info.xml")); |
200 |
jos.write(createInfoXML(visible, codeName, moduleName, nbm.toURI().toURL().toString(), specVersion, dependency).getBytes("UTF-8")); |
201 |
|
202 |
jos.putNextEntry(new ZipEntry("netbeans/")); |
203 |
jos.putNextEntry(new ZipEntry("netbeans/modules/")); |
204 |
jos.putNextEntry(new ZipEntry("netbeans/config/")); |
205 |
jos.putNextEntry(new ZipEntry("netbeans/config/Modules/")); |
206 |
jos.putNextEntry(new ZipEntry("netbeans/config/Modules/" + moduleFile + ".xml")); |
207 |
|
208 |
jos.write(getConfigXML(codeName, moduleFile, specVersion).getBytes("UTF-8")); |
209 |
|
210 |
|
211 |
jos.putNextEntry(new ZipEntry("netbeans/modules/" + moduleFile + ".jar")); |
212 |
|
213 |
FileInputStream fis = new FileInputStream(jar); |
214 |
FileUtil.copy(fis, jos); |
215 |
fis.close(); |
216 |
jar.delete(); |
217 |
jos.close(); |
218 |
nbms.add(nbm); |
219 |
|
220 |
return nbm; |
221 |
} |
222 |
|
223 |
protected void setUp() throws Exception { |
224 |
super.setUp(); |
225 |
this.clearWorkDir(); |
226 |
tmpDirectory = new File(getWorkDirPath(), "tmp"); |
227 |
tmpDirectory.mkdirs(); |
228 |
|
229 |
writeCatalog(); |
230 |
|
231 |
TestUtils.setUserDir(getWorkDirPath()); |
232 |
TestUtils.testInit(); |
233 |
|
234 |
MainLookup.register(new MyProvider()); |
235 |
assert Lookup.getDefault().lookup(MyProvider.class) != null; |
236 |
UpdateUnitProviderFactory.getDefault().refreshProviders(null, true); |
237 |
} |
238 |
|
239 |
public void testInternalUpdate() throws Exception { |
240 |
String dep = "org.yourorghere.dep.module"; |
241 |
String main = "org.yourorghere.main.module"; |
242 |
|
243 |
prepareNBM(dep, "1.0", false, null); |
244 |
prepareNBM(main, "1.0", true, dep + " > 1.0"); |
245 |
|
246 |
writeCatalog(); |
247 |
UpdateUnitProviderFactory.getDefault().refreshProviders(null, true); |
248 |
|
249 |
OperationContainer<InstallSupport> installContainer = OperationContainer.createForInstall(); |
250 |
|
251 |
UpdateUnit engineUnit = getUpdateUnit(main); |
252 |
assertNull("cannot be installed", engineUnit.getInstalled()); |
253 |
UpdateElement engineElement = getAvailableUpdate(engineUnit, 0); |
254 |
OperationInfo<InstallSupport> engineInfo = installContainer.add(engineElement); |
255 |
assertNotNull(engineInfo); |
256 |
|
257 |
|
258 |
UpdateUnit independentUnit = getUpdateUnit(dep); |
259 |
|
260 |
assertNull("cannot be installed", independentUnit.getInstalled()); |
261 |
UpdateElement independentElement = getAvailableUpdate(independentUnit, 0); |
262 |
assertEquals(independentElement.getSpecificationVersion(), "1.0"); |
263 |
|
264 |
OperationInfo<InstallSupport> independentInfo = installContainer.add(independentElement); |
265 |
assertNotNull(independentInfo); |
266 |
|
267 |
InstallSupport support = installContainer.getSupport(); |
268 |
assertNotNull(support); |
269 |
|
270 |
InstallSupport.Validator v = support.doDownload(null, false); |
271 |
assertNotNull(v); |
272 |
InstallSupport.Installer i = support.doValidate(v, null); |
273 |
assertNotNull(i); |
274 |
Restarter r = null; |
275 |
try { |
276 |
r = support.doInstall(i, null); |
277 |
} catch (OperationException ex) { |
278 |
if (OperationException.ERROR_TYPE.INSTALL == ex.getErrorType()) { |
279 |
// can ingore |
280 |
// module system cannot load the module either |
281 |
} else { |
282 |
fail(ex.toString()); |
283 |
} |
284 |
} |
285 |
|
286 |
assertTrue("element " + engineElement + " was not insetalled", engineUnit.getInstalled() != null); |
287 |
assertNull("Install update " + engineElement + " needs restart.", r); |
288 |
|
289 |
|
290 |
assertTrue("independent module was not installed together with the engine", independentUnit.getInstalled() != null); |
291 |
String specVersion = independentUnit.getInstalled().getSpecificationVersion(); |
292 |
|
293 |
assertTrue("independent version " + specVersion + " was installed together with the engine but 1.0 expected", specVersion.equals("1.0")); |
294 |
|
295 |
prepareNBM(dep, "1.1", false, null); |
296 |
writeCatalog(); |
297 |
UpdateUnitProviderFactory.getDefault().refreshProviders(null, true); |
298 |
|
299 |
independentUnit = getUpdateUnit(dep); |
300 |
assertEquals(1, independentUnit.getAvailableUpdates().size()); |
301 |
|
302 |
OperationContainer<InstallSupport> internalUpdateContainer = OperationContainer.createForInternalUpdate(); |
303 |
OperationInfo<InstallSupport> info = internalUpdateContainer.add(engineUnit.getInstalled()); |
304 |
assertNotNull("Can`t add element " + engineUnit.getInstalled() + " to internal updates container", info); |
305 |
|
306 |
assertFalse("No internal updates available for " + engineUnit, internalUpdateContainer.listAll().isEmpty()); |
307 |
|
308 |
Set<UpdateElement> required = info.getRequiredElements(); |
309 |
//for(OperationInfo <InstallSupport> in : internalUpdateContainer.listAll()) { |
310 |
// required.add(in.getUpdateElement()); |
311 |
// } |
312 |
assertFalse("Does not have internal update for " + engineUnit, required.isEmpty()); |
313 |
assertTrue("Has move than one internal update for " + engineUnit, required.size() == 1); |
314 |
UpdateElement expectedRequired = independentUnit.getAvailableUpdates().get(0); |
315 |
assertTrue("Has other internal update than version 1.1 for " + engineUnit, required.contains(expectedRequired)); |
316 |
|
317 |
|
318 |
InstallSupport os = internalUpdateContainer.getSupport(); |
319 |
assertNotNull(os); |
320 |
|
321 |
internalUpdateContainer.add(required); |
322 |
// internalUpdateContainer.remove(info); |
323 |
|
324 |
v = os.doDownload(null, false); |
325 |
assertNotNull(v); |
326 |
i = os.doValidate(v, null); |
327 |
assertNotNull(i); |
328 |
r = null; |
329 |
try { |
330 |
r = os.doInstall(i, null); |
331 |
} catch (OperationException ex) { |
332 |
if (OperationException.ERROR_TYPE.INSTALL == ex.getErrorType()) { |
333 |
// can ingore |
334 |
// module system cannot load the module either |
335 |
} else { |
336 |
fail(ex.toString()); |
337 |
} |
338 |
} |
339 |
|
340 |
assertNotNull("Installing update require restarting", r); |
341 |
} |
342 |
|
343 |
public UpdateUnit getUpdateUnit(String codeNameBase) { |
344 |
UpdateUnit uu = UpdateManagerImpl.getInstance().getUpdateUnit(codeNameBase); |
345 |
assertNotNull(uu); |
346 |
return uu; |
347 |
} |
348 |
|
349 |
public UpdateElement getAvailableUpdate(UpdateUnit updateUnit, int idx) { |
350 |
List<UpdateElement> available = updateUnit.getAvailableUpdates(); |
351 |
assertTrue(available.size() > idx); |
352 |
return available.get(idx); |
353 |
|
354 |
} |
355 |
|
356 |
protected void tearDown() throws Exception { |
357 |
super.tearDown(); |
358 |
} |
359 |
} |