001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU General
007: * Public License Version 2 only ("GPL") or the Common Development and Distribution
008: * License("CDDL") (collectively, the "License"). You may not use this file except in
009: * compliance with the License. You can obtain a copy of the License at
010: * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the
011: * License for the specific language governing permissions and limitations under the
012: * License. When distributing the software, include this License Header Notice in
013: * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Sun
014: * designates this particular file as subject to the "Classpath" exception as
015: * provided by Sun in the GPL Version 2 section of the License file that
016: * accompanied this code. If applicable, add the following below the License Header,
017: * with the fields enclosed by brackets [] replaced by your own identifying
018: * information: "Portions Copyrighted [year] [name of copyright owner]"
019: *
020: * Contributor(s):
021: *
022: * The Original Software is NetBeans. The Initial Developer of the Original Software
023: * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All
024: * Rights Reserved.
025: *
026: * If you wish your version of this file to be governed by only the CDDL or only the
027: * GPL Version 2, indicate your decision by adding "[Contributor] elects to include
028: * this software in this distribution under the [CDDL or GPL Version 2] license." If
029: * you do not indicate a single choice of license, a recipient has the option to
030: * distribute your version of this file under either the CDDL, the GPL Version 2 or
031: * to extend the choice of license to its licensees as provided above. However, if
032: * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then
033: * the option applies only if the new code is made subject to such option by the
034: * copyright holder.
035: */
036: package org.netbeans.installer.wizard.components.actions;
037:
038: import java.util.HashMap;
039: import java.util.List;
040: import java.util.Map;
041: import org.netbeans.installer.Installer;
042: import org.netbeans.installer.product.components.Product;
043: import org.netbeans.installer.product.Registry;
044: import org.netbeans.installer.product.filters.OrFilter;
045: import org.netbeans.installer.product.filters.ProductFilter;
046: import org.netbeans.installer.product.filters.RegistryFilter;
047: import org.netbeans.installer.utils.helper.DetailedStatus;
048: import org.netbeans.installer.utils.helper.Status;
049: import org.netbeans.installer.utils.helper.ErrorLevel;
050: import org.netbeans.installer.utils.LogManager;
051: import org.netbeans.installer.utils.ResourceUtils;
052: import org.netbeans.installer.utils.StringUtils;
053: import org.netbeans.installer.utils.SystemUtils;
054: import org.netbeans.installer.utils.exceptions.InstallationException;
055: import org.netbeans.installer.utils.progress.CompositeProgress;
056: import org.netbeans.installer.utils.progress.Progress;
057: import org.netbeans.installer.wizard.components.WizardAction;
058:
059: public class InstallAction extends WizardAction {
060: /////////////////////////////////////////////////////////////////////////////////
061: // Constants
062:
063: public static final String DEFAULT_TITLE = ResourceUtils.getString(
064: InstallAction.class, "IA.title"); // NOI18N
065:
066: public static final String DEFAULT_DESCRIPTION = ResourceUtils
067: .getString(InstallAction.class, "IA.description"); // NOI18N
068:
069: public static final String DEFAULT_PROGRESS_INSTALL_TITLE = ResourceUtils
070: .getString(InstallAction.class, "IA.progress.install.title"); // NOI18N
071:
072: public static final String PROGRESS_INSTALL_TITLE_PROPERTY = "progress.install.title"; //NOI18N
073:
074: public static final String DEFAULT_PROGRESS_ROLLBACK_TITLE = ResourceUtils
075: .getString(InstallAction.class,
076: "IA.progress.rollback.title"); // NOI18N
077:
078: public static final String PROGRESS_ROLLBACK_TITLE_PROPERTY = "progress.rollback.title"; //NOI18N
079:
080: public static final String DEFAULT_INSTALL_DEPENDENT_FAILED_EXCEPTION = ResourceUtils
081: .getString(InstallAction.class,
082: "IA.install.dependent.failed");//NOI18N
083:
084: public static final String INSTALL_DEPENDENT_FAILED_EXCEPTION_PROPERTY = "install.dependent.failed";
085: public static final String DEFAULT_INSTALL_UNKNOWN_ERROR = ResourceUtils
086: .getString(InstallAction.class, "IA.install.unknown.error");//NOI18N
087:
088: public static final String INSTALL_UNKNOWN_ERROR_PROPERTY = "install.unknown.error";
089:
090: public static final int INSTALLATION_ERROR_CODE = 127;//NOMAGI
091: /////////////////////////////////////////////////////////////////////////////////
092: // Instance
093:
094: private CompositeProgress overallProgress;
095: private Progress currentProgress;
096:
097: public InstallAction() {
098: setProperty(TITLE_PROPERTY, DEFAULT_TITLE);
099: setProperty(DESCRIPTION_PROPERTY, DEFAULT_DESCRIPTION);
100: setProperty(PROGRESS_INSTALL_TITLE_PROPERTY,
101: DEFAULT_PROGRESS_INSTALL_TITLE);
102: setProperty(PROGRESS_ROLLBACK_TITLE_PROPERTY,
103: DEFAULT_PROGRESS_ROLLBACK_TITLE);
104: setProperty(INSTALL_DEPENDENT_FAILED_EXCEPTION_PROPERTY,
105: DEFAULT_INSTALL_DEPENDENT_FAILED_EXCEPTION);
106: setProperty(INSTALL_UNKNOWN_ERROR_PROPERTY,
107: DEFAULT_INSTALL_UNKNOWN_ERROR);
108: }
109:
110: public boolean canExecuteForward() {
111: return Registry.getInstance().getProductsToInstall().size() > 0;
112: }
113:
114: public boolean isPointOfNoReturn() {
115: return true;
116: }
117:
118: public void execute() {
119: final Registry registry = Registry.getInstance();
120: final List<Product> products = registry.getProductsToInstall();
121: int percentageChunk = Progress.COMPLETE / products.size();
122: int percentageLeak = Progress.COMPLETE % products.size();
123: final Map<Product, Progress> progresses = new HashMap<Product, Progress>();
124:
125: overallProgress = new CompositeProgress();
126: overallProgress.setPercentage(percentageLeak);
127: overallProgress.synchronizeDetails(true);
128:
129: getWizardUi().setProgress(overallProgress);
130: for (int i = 0; i < products.size(); i++) {
131: // get the handle of the current item
132: final Product product = products.get(i);
133:
134: // initiate the progress for the current element
135: currentProgress = new Progress();
136:
137: overallProgress.addChild(currentProgress, percentageChunk);
138: overallProgress.setTitle(StringUtils.format(
139: getProperty(PROGRESS_INSTALL_TITLE_PROPERTY),
140: product.getDisplayName()));
141: boolean isProductRolledback = false;
142: try {
143: product.install(currentProgress);
144:
145: if (isCanceled()) {
146: overallProgress
147: .setTitle(StringUtils
148: .format(
149: getProperty(PROGRESS_ROLLBACK_TITLE_PROPERTY),
150: product.getDisplayName()));
151: product.rollback(currentProgress);
152: isProductRolledback = true;
153:
154: final RegistryFilter filter = new OrFilter(
155: new ProductFilter(
156: DetailedStatus.INSTALLED_SUCCESSFULLY),
157: new ProductFilter(
158: DetailedStatus.INSTALLED_WITH_WARNINGS));
159: for (Product toRollback : registry
160: .queryProducts(filter)) {
161: toRollback.setStatus(Status.TO_BE_UNINSTALLED);
162: }
163:
164: for (Product toRollback : registry
165: .getProductsToUninstall()) {
166: overallProgress
167: .setTitle(StringUtils
168: .format(
169: getProperty(PROGRESS_ROLLBACK_TITLE_PROPERTY),
170: toRollback
171: .getDisplayName()));
172: toRollback.rollback(progresses.get(toRollback));
173: }
174: break;
175: }
176:
177: progresses.put(product, currentProgress);
178:
179: // sleep a little so that the user can perceive that something
180: // is happening
181: SystemUtils.sleep(200);
182: } catch (Throwable e) {
183: if (!(e instanceof InstallationException)) {
184: e = new InstallationException(
185: getProperty(INSTALL_UNKNOWN_ERROR_PROPERTY),
186: e);
187: }
188: // do not override already set exit code
189: if (System.getProperties().get(
190: Installer.EXIT_CODE_PROPERTY) == null) {
191: System.getProperties().put(
192: Installer.EXIT_CODE_PROPERTY,
193: new Integer(INSTALLATION_ERROR_CODE));
194: }
195: // adjust the product's status and save this error - it will
196: // be reused later at the PostInstallSummary
197: product.setStatus(Status.NOT_INSTALLED);
198: product.setInstallationError(e);
199:
200: // since the current product failed to install, we should cancel the
201: // installation of the products that may require this one
202: for (Product dependent : registry.getProducts()) {
203: if ((dependent.getStatus() == Status.TO_BE_INSTALLED)
204: && registry.satisfiesRequirement(product,
205: dependent)) {
206: final String exceptionName = StringUtils
207: .format(
208: getProperty(INSTALL_DEPENDENT_FAILED_EXCEPTION_PROPERTY),
209: dependent.getDisplayName(),
210: product.getDisplayName());
211:
212: final InstallationException dependentError = new InstallationException(
213: exceptionName, e);
214:
215: dependent.setStatus(Status.NOT_INSTALLED);
216: dependent.setInstallationError(dependentError);
217:
218: products.remove(dependent);
219: }
220: }
221:
222: if (!isProductRolledback) {
223: try {
224: overallProgress
225: .setTitle(StringUtils
226: .format(
227: getProperty(PROGRESS_ROLLBACK_TITLE_PROPERTY),
228: product
229: .getDisplayName()));
230: product.rollback(currentProgress);
231: } catch (Exception uie) {
232: LogManager.log(uie);
233: }
234: }
235: overallProgress.removeChild(currentProgress);
236: final int productsToInstallSize = registry
237: .getProductsToInstall().size();
238: if (productsToInstallSize > 0) {
239: final int theRestOfPercentage = Progress.COMPLETE
240: - overallProgress.getPercentage();
241: percentageChunk = theRestOfPercentage
242: / productsToInstallSize;
243: percentageLeak = theRestOfPercentage
244: % productsToInstallSize;
245: overallProgress.addPercentage(percentageLeak);
246: }
247:
248: // finally notify the user of what has happened
249: LogManager.log(ErrorLevel.ERROR, e);
250: }
251: }
252: }
253:
254: public void cancel() {
255: if (currentProgress != null) {
256: currentProgress.setCanceled(true);
257: }
258:
259: if (overallProgress != null) {
260: overallProgress.setCanceled(true);
261: }
262:
263: super.cancel();
264: }
265: }
|