1.1 --- a/modulemanagement/manifest.mf Thu Jan 12 16:29:02 2012 -0500
1.2 +++ b/modulemanagement/manifest.mf Sat Jan 21 22:56:16 2012 +0100
1.3 @@ -1,5 +1,5 @@
1.4 Manifest-Version: 1.0
1.5 OpenIDE-Module: org.netbeans.modules.modulemanagement
1.6 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/modulemanagement/Bundle.properties
1.7 -OpenIDE-Module-Specification-Version: 1.4
1.8 +OpenIDE-Module-Specification-Version: 1.5
1.9
2.1 --- a/modulemanagement/src/org/netbeans/modules/modulemanagement/Bundle.properties Thu Jan 12 16:29:02 2012 -0500
2.2 +++ b/modulemanagement/src/org/netbeans/modules/modulemanagement/Bundle.properties Sat Jan 21 22:56:16 2012 +0100
2.3 @@ -45,16 +45,6 @@
2.4 OpenIDE-Module-Short-Description=Provides CLI interface to query running NetBeans system
2.5
2.6
2.7 -MSG_ModuleListFooter=\
2.8 --------------------------------------------------- --------------- -------
2.9 -
2.10 -MSG_ModuleListHeader=\
2.11 -Module CodeName Spec. Version State\n\
2.12 --------------------------------------------------- --------------- -------
2.13 -MSG_ModuleListLine=\
2.14 -{0} {4} {7,choice,0#disabled|1#enabled}
2.15 -
2.16 -
2.17 # {0} - the file
2.18 ERR_FileNotFound=File {0} cannot be found
2.19 ERR_NotModule=File {0} does not seem to be a module
3.1 --- a/modulemanagement/src/org/netbeans/modules/modulemanagement/ModuleOptions.java Thu Jan 12 16:29:02 2012 -0500
3.2 +++ b/modulemanagement/src/org/netbeans/modules/modulemanagement/ModuleOptions.java Sat Jan 21 22:56:16 2012 +0100
3.3 @@ -48,6 +48,7 @@
3.4 import java.io.PrintStream;
3.5 import java.util.Arrays;
3.6 import java.util.Collection;
3.7 +import java.util.Collections;
3.8 import java.util.HashSet;
3.9 import java.util.Iterator;
3.10 import java.util.List;
3.11 @@ -55,24 +56,26 @@
3.12 import java.util.Set;
3.13 import java.util.jar.JarFile;
3.14 import java.util.logging.Logger;
3.15 -import org.netbeans.api.autoupdate.OperationContainer;
3.16 -import org.netbeans.api.autoupdate.OperationException;
3.17 -import org.netbeans.api.autoupdate.OperationSupport;
3.18 -import org.netbeans.api.autoupdate.UpdateManager;
3.19 -import org.netbeans.api.autoupdate.UpdateUnit;
3.20 +import java.util.regex.Matcher;
3.21 +import java.util.regex.Pattern;
3.22 +import java.util.regex.PatternSyntaxException;
3.23 +import org.netbeans.api.autoupdate.*;
3.24 +import org.netbeans.api.autoupdate.InstallSupport.Installer;
3.25 +import org.netbeans.api.autoupdate.InstallSupport.Validator;
3.26 +import org.netbeans.api.autoupdate.OperationSupport.Restarter;
3.27 import org.netbeans.api.sendopts.CommandException;
3.28 import org.netbeans.spi.sendopts.Env;
3.29 import org.netbeans.spi.sendopts.Option;
3.30 +import org.netbeans.spi.sendopts.OptionGroups;
3.31 import org.netbeans.spi.sendopts.OptionProcessor;
3.32 import org.openide.filesystems.FileLock;
3.33 import org.openide.filesystems.FileObject;
3.34 import org.openide.filesystems.FileSystem;
3.35 import org.openide.filesystems.FileUtil;
3.36 import org.openide.modules.ModuleInfo;
3.37 -import org.openide.util.Lookup;
3.38 -import org.openide.util.LookupEvent;
3.39 -import org.openide.util.LookupListener;
3.40 -import org.openide.util.NbBundle;
3.41 +import org.openide.util.*;
3.42 +
3.43 +import static org.netbeans.modules.modulemanagement.Bundle.*;
3.44
3.45 /**
3.46 *
3.47 @@ -86,76 +89,77 @@
3.48 private Option install;
3.49 private Option disable;
3.50 private Option enable;
3.51 + private Option update;
3.52 + private Option refresh;
3.53 + private Option both;
3.54
3.55 /** Creates a new instance of ModuleOptions */
3.56 public ModuleOptions() {
3.57 }
3.58
3.59 - private void init() {
3.60 - if (list != null) {
3.61 - return;
3.62 + @NbBundle.Messages({
3.63 + "MSG_UpdateModules=Updates all or specified modules",
3.64 + "MSG_RefreshModules=Refresh catalog of available modules"
3.65 + })
3.66 + private Option init() {
3.67 + if (both != null) {
3.68 + return both;
3.69 }
3.70
3.71 String b = "org.netbeans.modules.modulemanagement.Bundle";
3.72 list = Option.shortDescription(
3.73 - Option.withoutArgument(Option.NO_SHORT_NAME, "listmodules"), b, "MSG_ListModules"); // NOI18N
3.74 + Option.withoutArgument(Option.NO_SHORT_NAME, "list"), b, "MSG_ListModules"); // NOI18N
3.75 install = Option.shortDescription(
3.76 - Option.additionalArguments(Option.NO_SHORT_NAME, "installmodules"), b, "MSG_InstallModules"); // NOI18N
3.77 + Option.additionalArguments(Option.NO_SHORT_NAME, "install"), b, "MSG_InstallModules"); // NOI18N
3.78 disable = Option.shortDescription(
3.79 - Option.additionalArguments(Option.NO_SHORT_NAME, "disablemodules"), b, "MSG_DisableModules"); // NOI18N
3.80 + Option.additionalArguments(Option.NO_SHORT_NAME, "disable"), b, "MSG_DisableModules"); // NOI18N
3.81 enable = Option.shortDescription(
3.82 - Option.additionalArguments(Option.NO_SHORT_NAME, "enablemodules"), b, "MSG_EnableModules"); // NOI18N
3.83 + Option.additionalArguments(Option.NO_SHORT_NAME, "enable"), b, "MSG_EnableModules"); // NOI18N
3.84 + update = Option.shortDescription(
3.85 + Option.additionalArguments(Option.NO_SHORT_NAME, "update"), b, "MSG_UpdateModules"); // NOI18N
3.86 + refresh = Option.shortDescription(
3.87 + Option.additionalArguments(Option.NO_SHORT_NAME, "refresh"), b, "MSG_RefreshModules"); // NOI18N
3.88 +
3.89 + Option oper = OptionGroups.oneOf(list, install, disable, enable, update, refresh);
3.90 + Option modules = Option.withoutArgument(Option.NO_SHORT_NAME, "modules");
3.91 + both = OptionGroups.allOf(modules, oper);
3.92 + return both;
3.93 }
3.94
3.95 public Set<Option> getOptions() {
3.96 - init();
3.97 - Set<Option> s = new HashSet<Option>();
3.98 - s.add(list);
3.99 - s.add(install);
3.100 - s.add(disable);
3.101 - s.add(enable);
3.102 - return s;
3.103 + return Collections.singleton(init());
3.104 + }
3.105 +
3.106 + private void refresh(Env env) throws CommandException {
3.107 + for (UpdateUnitProvider p : UpdateUnitProviderFactory.getDefault().getUpdateUnitProviders(true)) {
3.108 + try {
3.109 + env.getOutputStream().println("Refreshing " + p.getDisplayName());
3.110 + p.refresh(null, true);
3.111 + } catch (IOException ex) {
3.112 + throw (CommandException)new CommandException(33, ex.getMessage()).initCause(ex);
3.113 + }
3.114 + }
3.115 }
3.116
3.117 + @NbBundle.Messages({
3.118 + "MSG_ListHeader_CodeName=Code Name",
3.119 + "MSG_ListHeader_Version=Version",
3.120 + "MSG_ListHeader_State=State"
3.121 + })
3.122 private void listAllModules(PrintStream out) {
3.123 - Collection<? extends ModuleInfo> modules = Lookup.getDefault().lookupAll(ModuleInfo.class);
3.124 - Integer number = new Integer(modules.size());
3.125 - out.println(NbBundle.getMessage(ModuleOptions.class, "MSG_ModuleListHeader", number));
3.126 - Iterator<? extends ModuleInfo> it = modules.iterator();
3.127 - while (it.hasNext()) {
3.128 - ModuleInfo module = it.next();
3.129 - Object[] args = {
3.130 - fixedLength(module.getCodeName(), 50),
3.131 - fixedLength(module.getCodeNameBase(), 50),
3.132 - new Integer(module.getCodeNameRelease()),
3.133 - fixedLength(module.getDisplayName(), 50),
3.134 - fixedLength(module.getSpecificationVersion() == null ? "" : module.getSpecificationVersion().toString(), 15),
3.135 - fixedLength(module.getImplementationVersion(), 15),
3.136 - fixedLength(module.getBuildVersion(), 15),
3.137 - new Integer(module.isEnabled() ? 1 : 0),
3.138 - };
3.139 - out.println(NbBundle.getMessage(ModuleOptions.class, "MSG_ModuleListLine", args));
3.140 + List<UpdateUnit> modules = UpdateManager.getDefault().getUpdateUnits();
3.141 +
3.142 + PrintTable table = new PrintTable(
3.143 + MSG_ListHeader_CodeName(), MSG_ListHeader_Version(), MSG_ListHeader_State()
3.144 + );
3.145 + table.setLimits(50, -1, -1);
3.146 + for (UpdateUnit uu : modules) {
3.147 + table.addRow(Status.toArray(uu));
3.148 }
3.149 - out.println(NbBundle.getMessage(ModuleOptions.class, "MSG_ModuleListFooter", number));
3.150 + table.write(out);
3.151 out.flush();
3.152 }
3.153
3.154 - private static String fixedLength(String s, int len) {
3.155 - if (s == null) {
3.156 - return null;
3.157 - }
3.158 - if (s.length() >= len) {
3.159 - return s.substring(0, len);
3.160 - } else {
3.161 - StringBuffer sb = new StringBuffer(len);
3.162 - sb.append(s);
3.163 - while (sb.length() < len) {
3.164 - sb.append(' ');
3.165 - }
3.166 - return sb.toString();
3.167 - }
3.168 - }
3.169 -
3.170 private static <T extends Throwable> T initCause(T t, Throwable cause) {
3.171 t.initCause(cause);
3.172 return t;
3.173 @@ -168,70 +172,7 @@
3.174
3.175 try {
3.176 if (optionValues.containsKey(install)) {
3.177 - String[] args = optionValues.get(install);
3.178 - for (String fileName : args) {
3.179 - File f = new File(env.getCurrentDirectory(), fileName);
3.180 - if (!f.exists()) {
3.181 - f = new File(fileName);
3.182 - }
3.183 - if (!f.exists()) {
3.184 - throw new CommandException(5, NbBundle.getMessage(ModuleOptions.class, "ERR_FileNotFound", f)); // NOI18N
3.185 - }
3.186 -
3.187 - JarFile jar = new JarFile(f);
3.188 - String cnb = jar.getManifest().getMainAttributes().getValue("OpenIDE-Module"); // NOI18N
3.189 - if (cnb == null) {
3.190 - throw new CommandException(6, NbBundle.getMessage(ModuleOptions.class, "ERR_NotModule", f)); // NOI18N
3.191 - }
3.192 - {
3.193 - int slash = cnb.indexOf('/');
3.194 - if (slash >= 0) {
3.195 - cnb = cnb.substring(0, slash);
3.196 - }
3.197 - }
3.198 -
3.199 - final File file = f;
3.200 - final String codebase = cnb;
3.201 - final FileObject root = FileUtil.getConfigRoot();
3.202 - final FileObject dir = FileUtil.createFolder(root, "Modules");
3.203 - final String fn = cnb.replace('.', '-') + ".xml";
3.204 -
3.205 -
3.206 - class X implements FileSystem.AtomicAction {
3.207 - FileObject conf = dir.getFileObject(fn);
3.208 -
3.209 - public void run() throws IOException {
3.210 - conf = FileUtil.createData(dir, fn);
3.211 - FileLock lock = conf.lock();
3.212 - PrintStream os = new PrintStream(conf.getOutputStream(lock));
3.213 -
3.214 - os.print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
3.215 - os.print("<!DOCTYPE module PUBLIC \"-//NetBeans//DTD Module Status 1.0//EN\"\n");
3.216 - os.print(" \"http://www.netbeans.org/dtds/module-status-1_0.dtd\">\n");
3.217 - os.print("<module name=\"" + codebase + "\">\n");
3.218 - os.print(" <param name=\"autoload\">false</param>\n");
3.219 - os.print(" <param name=\"eager\">false</param>\n");
3.220 - os.print(" <param name=\"enabled\">true</param>\n");
3.221 - os.print(" <param name=\"jar\">" + file + "</param>\n");
3.222 - os.print(" <param name=\"release\">1</param>\n");
3.223 - os.print(" <param name=\"reloadable\">false</param>\n");
3.224 - os.print(" <param name=\"specversion\">1.25</param>\n");
3.225 - os.print("</module>\n");
3.226 -
3.227 - os.close();
3.228 - lock.releaseLock();
3.229 - }
3.230 - }
3.231 - X x = new X();
3.232 -
3.233 - if (x.conf != null) {
3.234 - throw new CommandException(7, NbBundle.getMessage(ModuleOptions.class, "ERR_AlreadyInstalled", f, cnb)); // NOI18N
3.235 - }
3.236 -
3.237 - dir.getFileSystem().runAtomicAction(x);
3.238 -
3.239 - waitFor(cnb, true);
3.240 - }
3.241 + install(env, optionValues.get(install));
3.242 }
3.243
3.244 if (optionValues.containsKey(disable)) {
3.245 @@ -240,7 +181,6 @@
3.246
3.247 if (optionValues.containsKey(enable)) {
3.248 changeModuleState(optionValues.get(enable), true);
3.249 -
3.250 }
3.251 } catch (InterruptedException ex) {
3.252 throw initCause(new CommandException(4), ex);
3.253 @@ -249,97 +189,12 @@
3.254 } catch (OperationException ex) {
3.255 throw initCause(new CommandException(4), ex);
3.256 }
3.257 - }
3.258 -
3.259 - private static void waitFor(final String codebase, final boolean shouldBeEnabled) throws IOException, InterruptedException, CommandException {
3.260 - LOG.fine("waitFor: " + codebase + " state: " + shouldBeEnabled); // NOI18N
3.261 -
3.262 - final Lookup.Result<ModuleInfo> res = Lookup.getDefault().lookupResult(ModuleInfo.class);
3.263 - res.allInstances();
3.264 -
3.265 - class L implements LookupListener, PropertyChangeListener {
3.266 - private boolean go;
3.267 - private Set<ModuleInfo> listening = new HashSet<ModuleInfo>();
3.268 -
3.269 - public synchronized void resultChanged(LookupEvent ev) {
3.270 - notifyAll();
3.271 - go = true;
3.272 - LOG.fine("go set to true by a listener"); // NOI18N
3.273 - }
3.274 -
3.275 - public synchronized void propertyChange(PropertyChangeEvent ev) {
3.276 - notifyAll();
3.277 - go = true;
3.278 - LOG.fine("go set to true by a property change listener"); // NOI18N
3.279 - }
3.280 -
3.281 - public void waitFor() throws CommandException, InterruptedException {
3.282 - Collection<? extends ModuleInfo> modules;
3.283 -
3.284 - for(;;) {
3.285 - synchronized (this) {
3.286 - go = false;
3.287 - LOG.fine("go = false");
3.288 - }
3.289 -
3.290 - modules = res.allInstances();
3.291 -
3.292 - boolean found = false;
3.293 - for (ModuleInfo m : modules) {
3.294 - if (m.getCodeNameBase().equals(codebase)) {
3.295 - LOG.fine("found code base: " + codebase + " as " + m); // NOI18N
3.296 - found = true;
3.297 - if (shouldBeEnabled) {
3.298 - if (m.isEnabled()) {
3.299 - return;
3.300 - }
3.301 - } else {
3.302 - if (!m.isEnabled()) {
3.303 - return;
3.304 - }
3.305 - }
3.306 - listening.add(m);
3.307 - m.addPropertyChangeListener(this);
3.308 - break;
3.309 - }
3.310 - }
3.311 -
3.312 - if (!shouldBeEnabled && !found) {
3.313 - // all modules scanned but non of it has our codename base
3.314 - return;
3.315 - }
3.316 -
3.317 - synchronized (this) {
3.318 - LOG.fine("waiting 10000"); // NOI18N
3.319 - if (!go) {
3.320 - wait(10000);
3.321 - }
3.322 - if (!go) {
3.323 - LOG.fine("No event received: " + go + " exiting"); // NOI18N
3.324 - throw new CommandException(4, NbBundle.getMessage(ModuleOptions.class, "ERR_TimeOut", codebase, shouldBeEnabled ? 1 : 0)); // NOI18N
3.325 - }
3.326 - }
3.327 - }
3.328 - }
3.329 -
3.330 - public void cleanUp() {
3.331 - res.removeLookupListener(this);
3.332 - for (ModuleInfo m : listening) {
3.333 - m.removePropertyChangeListener(this);
3.334 - }
3.335 - }
3.336 + if (optionValues.containsKey(update)) {
3.337 + updateModules(env, optionValues.get(update));
3.338 }
3.339 -
3.340 - L list = new L();
3.341 - try {
3.342 - res.addLookupListener(list);
3.343 - res.allItems();
3.344 - list.waitFor();
3.345 - } finally {
3.346 - list.cleanUp();
3.347 + if (optionValues.containsKey(refresh)) {
3.348 + refresh(env);
3.349 }
3.350 -
3.351 - LOG.fine("waitFor finished");
3.352 }
3.353
3.354 private void changeModuleState(String[] cnbs, boolean enable) throws IOException, CommandException, InterruptedException, OperationException {
3.355 @@ -367,5 +222,116 @@
3.356 support.doOperation(null);
3.357 }
3.358
3.359 + @NbBundle.Messages({
3.360 + "MSG_UpdateNoMatch=Nothing to update. The pattern {0} has no match among available updates.",
3.361 + "MSG_Update=Will update {0}@{1} to version {2}"
3.362 + })
3.363 + private void updateModules(Env env, String[] pattern) throws CommandException {
3.364 + Pattern[] pats = findMatcher(env, pattern);
3.365 +
3.366 + List<UpdateUnit> units = UpdateManager.getDefault().getUpdateUnits();
3.367 + OperationContainer<InstallSupport> operate = OperationContainer.createForInternalUpdate();
3.368 + for (UpdateUnit uu : units) {
3.369 + if (uu.getInstalled() == null) {
3.370 + continue;
3.371 + }
3.372 + final List<UpdateElement> updates = uu.getAvailableUpdates();
3.373 + if (updates.isEmpty()) {
3.374 + continue;
3.375 + }
3.376 + if (!matches(uu.getCodeName(), pats)) {
3.377 + continue;
3.378 + }
3.379 + final UpdateElement ue = updates.get(0);
3.380 + env.getOutputStream().println(
3.381 + Bundle.MSG_Update(uu.getCodeName(), uu.getInstalled().getSpecificationVersion(), ue.getSpecificationVersion()
3.382 + ));
3.383 + operate.add(ue);
3.384 + }
3.385 + final InstallSupport support = operate.getSupport();
3.386 + if (support == null) {
3.387 + env.getOutputStream().println(Bundle.MSG_UpdateNoMatch(Arrays.asList(pats)));
3.388 + return;
3.389 + }
3.390 + try {
3.391 + final Validator res1 = support.doDownload(null, true);
3.392 + Installer res2 = support.doValidate(res1, null);
3.393 + Restarter res3 = support.doInstall(res2, null);
3.394 + if (res3 != null) {
3.395 + support.doRestart(res3, null);
3.396 + }
3.397 + } catch (OperationException ex) {
3.398 + throw (CommandException)new CommandException(33, ex.getMessage()).initCause(ex);
3.399 + }
3.400 + }
3.401 +
3.402 + @NbBundle.Messages({
3.403 + "MSG_CantCompileRegex=Cannot understand regular expession '{0}'"
3.404 + })
3.405 + private static Pattern[] findMatcher(Env env, String[] pattern) {
3.406 + Pattern[] arr = new Pattern[pattern.length];
3.407 + for (int i = 0; i < arr.length; i++) {
3.408 + try {
3.409 + arr[i] = Pattern.compile(pattern[i]);
3.410 + } catch (PatternSyntaxException e) {
3.411 + env.getErrorStream().println(Bundle.MSG_CantCompileRegex(pattern[i]));
3.412 + }
3.413 + }
3.414 + return arr;
3.415 + }
3.416 +
3.417 + private static boolean matches(String txt, Pattern[] pats) {
3.418 + for (Pattern p : pats) {
3.419 + if (p == null) {
3.420 + continue;
3.421 + }
3.422 + if (p.matcher(txt).matches()) {
3.423 + return true;
3.424 + }
3.425 + }
3.426 + return false;
3.427 + }
3.428 +
3.429 + @NbBundle.Messages({
3.430 + "MSG_Installing=Installing {0}@{1}",
3.431 + "MSG_InstallNoMatch=Cannot install. No match for {0}."
3.432 + })
3.433 + private void install(Env env, String[] pattern) throws CommandException {
3.434 + Pattern[] pats = findMatcher(env, pattern);
3.435 +
3.436 + List<UpdateUnit> units = UpdateManager.getDefault().getUpdateUnits();
3.437 + OperationContainer<InstallSupport> operate = OperationContainer.createForInstall();
3.438 + for (UpdateUnit uu : units) {
3.439 + if (uu.getInstalled() != null) {
3.440 + continue;
3.441 + }
3.442 + if (!matches(uu.getCodeName(), pats)) {
3.443 + continue;
3.444 + }
3.445 + if (uu.getAvailableUpdates().isEmpty()) {
3.446 + continue;
3.447 + }
3.448 + UpdateElement ue = uu.getAvailableUpdates().get(0);
3.449 + env.getOutputStream().println(
3.450 + Bundle.MSG_Installing(uu.getCodeName(), ue.getSpecificationVersion()));
3.451 + operate.add(ue);
3.452 + }
3.453 + final InstallSupport support = operate.getSupport();
3.454 + if (support == null) {
3.455 + env.getOutputStream().println(Bundle.MSG_InstallNoMatch(Arrays.asList(pats)));
3.456 + return;
3.457 + }
3.458 + try {
3.459 + final Validator res1 = support.doDownload(null, true);
3.460 + Installer res2 = support.doValidate(res1, null);
3.461 + Restarter res3 = support.doInstall(res2, null);
3.462 + if (res3 != null) {
3.463 + support.doRestart(res3, null);
3.464 + }
3.465 + } catch (OperationException ex) {
3.466 + throw (CommandException) new CommandException(33, ex.getMessage()).initCause(ex);
3.467 + }
3.468 + }
3.469 +
3.470 }
3.471
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/modulemanagement/src/org/netbeans/modules/modulemanagement/PrintTable.java Sat Jan 21 22:56:16 2012 +0100
4.3 @@ -0,0 +1,128 @@
4.4 +/*
4.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4.6 + *
4.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
4.8 + *
4.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
4.10 + * Other names may be trademarks of their respective owners.
4.11 + *
4.12 + * The contents of this file are subject to the terms of either the GNU
4.13 + * General Public License Version 2 only ("GPL") or the Common
4.14 + * Development and Distribution License("CDDL") (collectively, the
4.15 + * "License"). You may not use this file except in compliance with the
4.16 + * License. You can obtain a copy of the License at
4.17 + * http://www.netbeans.org/cddl-gplv2.html
4.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
4.19 + * specific language governing permissions and limitations under the
4.20 + * License. When distributing the software, include this License Header
4.21 + * Notice in each file and include the License file at
4.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
4.23 + * particular file as subject to the "Classpath" exception as provided
4.24 + * by Oracle in the GPL Version 2 section of the License file that
4.25 + * accompanied this code. If applicable, add the following below the
4.26 + * License Header, with the fields enclosed by brackets [] replaced by
4.27 + * your own identifying information:
4.28 + * "Portions Copyrighted [year] [name of copyright owner]"
4.29 + *
4.30 + * If you wish your version of this file to be governed by only the CDDL
4.31 + * or only the GPL Version 2, indicate your decision by adding
4.32 + * "[Contributor] elects to include this software in this distribution
4.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
4.34 + * single choice of license, a recipient has the option to distribute
4.35 + * your version of this file under either the CDDL, the GPL Version 2 or
4.36 + * to extend the choice of license to its licensees as provided above.
4.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
4.38 + * Version 2 license, then the option applies only if the new code is
4.39 + * made subject to such option by the copyright holder.
4.40 + *
4.41 + * Contributor(s):
4.42 + *
4.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
4.44 + */
4.45 +package org.netbeans.modules.modulemanagement;
4.46 +
4.47 +import java.io.PrintStream;
4.48 +import java.util.ArrayList;
4.49 +import java.util.List;
4.50 +
4.51 +/** Prints table formated for output stream.
4.52 + *
4.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
4.54 + */
4.55 +final class PrintTable {
4.56 + private final String[] names;
4.57 + private final List<String[]> data;
4.58 + private int[] limits;
4.59 +
4.60 + public PrintTable(String... fieldNames) {
4.61 + names = fieldNames;
4.62 + data = new ArrayList<String[]>();
4.63 + }
4.64 +
4.65 + public void setLimits(int... limits) {
4.66 + assert limits.length == names.length;
4.67 + this.limits = limits;
4.68 + }
4.69 +
4.70 + public void addRow(String... fields) {
4.71 + data.add(fields);
4.72 + }
4.73 +
4.74 + public void write(PrintStream ps) {
4.75 + int[] lengths = new int[names.length];
4.76 + length(names, lengths, limits);
4.77 + for (String[] arr : data) {
4.78 + length(arr, lengths, limits);
4.79 + }
4.80 +
4.81 + printRow(ps, names, lengths, limits);
4.82 + printSeparator(ps, lengths);
4.83 + for (String[] arr : data) {
4.84 + printRow(ps, arr, lengths, limits);
4.85 + }
4.86 + printSeparator(ps, lengths);
4.87 + }
4.88 +
4.89 + private static void length(String[] data, int[] lengths, int[] limits) {
4.90 + assert data.length == lengths.length;
4.91 + for (int i = 0; i < data.length; i++) {
4.92 + int l = data[i].length();
4.93 + if (limits != null && limits[i] >= 0 && l > limits[i]) {
4.94 + l = limits[i];
4.95 + }
4.96 + if (lengths[i] < l) {
4.97 + lengths[i] = l;
4.98 + }
4.99 + }
4.100 + }
4.101 +
4.102 + private static void printRow(PrintStream ps, String[] data, int[] lengths, int[] limits) {
4.103 + assert data.length == lengths.length;
4.104 + String sep = "";
4.105 + for (int i = 0; i < data.length; i++) {
4.106 + ps.print(sep);
4.107 + String d = data[i];
4.108 + if (limits != null && limits[i] >= 0 && d.length() > limits[i]) {
4.109 + d = d.substring(0, limits[i]);
4.110 + }
4.111 + ps.print(d);
4.112 + int missing = lengths[i] - d.length();
4.113 + while (missing-- > 0) {
4.114 + ps.print(' ');
4.115 + }
4.116 + sep = " ";
4.117 + }
4.118 + ps.println();
4.119 + }
4.120 + private static void printSeparator(PrintStream ps, int[] lengths) {
4.121 + String sep = "";
4.122 + for (int i = 0; i < lengths.length; i++) {
4.123 + ps.print(sep);
4.124 + for (int j = 0; j < lengths[i]; j++) {
4.125 + ps.print('-');
4.126 + }
4.127 + sep = " ";
4.128 + }
4.129 + ps.println();
4.130 + }
4.131 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/modulemanagement/src/org/netbeans/modules/modulemanagement/Status.java Sat Jan 21 22:56:16 2012 +0100
5.3 @@ -0,0 +1,126 @@
5.4 +/*
5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
5.6 + *
5.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5.8 + *
5.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
5.10 + * Other names may be trademarks of their respective owners.
5.11 + *
5.12 + * The contents of this file are subject to the terms of either the GNU
5.13 + * General Public License Version 2 only ("GPL") or the Common
5.14 + * Development and Distribution License("CDDL") (collectively, the
5.15 + * "License"). You may not use this file except in compliance with the
5.16 + * License. You can obtain a copy of the License at
5.17 + * http://www.netbeans.org/cddl-gplv2.html
5.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
5.19 + * specific language governing permissions and limitations under the
5.20 + * License. When distributing the software, include this License Header
5.21 + * Notice in each file and include the License file at
5.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
5.23 + * particular file as subject to the "Classpath" exception as provided
5.24 + * by Oracle in the GPL Version 2 section of the License file that
5.25 + * accompanied this code. If applicable, add the following below the
5.26 + * License Header, with the fields enclosed by brackets [] replaced by
5.27 + * your own identifying information:
5.28 + * "Portions Copyrighted [year] [name of copyright owner]"
5.29 + *
5.30 + * If you wish your version of this file to be governed by only the CDDL
5.31 + * or only the GPL Version 2, indicate your decision by adding
5.32 + * "[Contributor] elects to include this software in this distribution
5.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
5.34 + * single choice of license, a recipient has the option to distribute
5.35 + * your version of this file under either the CDDL, the GPL Version 2 or
5.36 + * to extend the choice of license to its licensees as provided above.
5.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
5.38 + * Version 2 license, then the option applies only if the new code is
5.39 + * made subject to such option by the copyright holder.
5.40 + *
5.41 + * Contributor(s):
5.42 + *
5.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
5.44 + */
5.45 +package org.netbeans.modules.modulemanagement;
5.46 +
5.47 +import java.util.List;
5.48 +import org.netbeans.api.autoupdate.UpdateElement;
5.49 +import org.netbeans.api.autoupdate.UpdateUnit;
5.50 +import org.openide.modules.ModuleInfo;
5.51 +import org.openide.util.Lookup;
5.52 +import org.openide.util.NbBundle;
5.53 +
5.54 +/**
5.55 + *
5.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
5.57 + */
5.58 +final class Status {
5.59 +
5.60 + static String[] toArray(UpdateUnit uu) {
5.61 + if (uu.getInstalled() != null) {
5.62 + return new String[] {
5.63 + uu.getCodeName(),
5.64 + uu.getInstalled().getSpecificationVersion(),
5.65 + Status.installed(uu).toString()
5.66 + };
5.67 + } else {
5.68 + List<UpdateElement> updates = uu.getAvailableUpdates();
5.69 + if (updates.isEmpty()) {
5.70 + return new String[] {
5.71 + uu.getCodeName(),
5.72 + "N/A", "N/A"
5.73 + };
5.74 + }
5.75 + UpdateElement first = updates.get(0);
5.76 + return new String[] {
5.77 + uu.getCodeName(),
5.78 + first.getSpecificationVersion(),
5.79 + Status.update(uu).toString()
5.80 + };
5.81 + }
5.82 + }
5.83 +
5.84 + final String txt;
5.85 +
5.86 + private Status(String txt) {
5.87 + this.txt = txt;
5.88 + }
5.89 +
5.90 + @NbBundle.Messages({
5.91 + "MSG_Enabled=Enabled",
5.92 + "MSG_Disabled=Installed",
5.93 + "MSG_UpdateAvailable=Upgrade to {0}"
5.94 + })
5.95 + private static Status installed(UpdateUnit uu) {
5.96 + assert uu.getInstalled() != null;
5.97 + String install;
5.98 + ModuleInfo mi = find(uu.getCodeName());
5.99 + List<UpdateElement> updates = uu.getAvailableUpdates();
5.100 + if (!updates.isEmpty()) {
5.101 + install = Bundle.MSG_UpdateAvailable(updates.get(0).getSpecificationVersion());
5.102 + } else {
5.103 + install = mi.isEnabled() ? Bundle.MSG_Enabled() : Bundle.MSG_Disabled();
5.104 + }
5.105 +
5.106 + return new Status(install);
5.107 + }
5.108 + @NbBundle.Messages({
5.109 + "MSG_Updateable=Available"
5.110 + })
5.111 + private static Status update(UpdateUnit uu) {
5.112 + assert uu.getInstalled() == null && !uu.getAvailableUpdates().isEmpty();
5.113 + return new Status(Bundle.MSG_Updateable());
5.114 + }
5.115 +
5.116 + @Override
5.117 + public String toString() {
5.118 + return txt;
5.119 + }
5.120 +
5.121 + private static ModuleInfo find(String cnb) {
5.122 + for (ModuleInfo mi : Lookup.getDefault().lookupAll(ModuleInfo.class)) {
5.123 + if (cnb.equals(mi.getCodeNameBase())) {
5.124 + return mi;
5.125 + }
5.126 + }
5.127 + return null;
5.128 + }
5.129 +}