001: /*
002: * uDig - User Friendly Desktop Internet GIS client
003: * http://udig.refractions.net
004: * (C) 2004, Refractions Research Inc.
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: */
017: package net.refractions.udig.catalog.ui.preferences;
018:
019: import java.io.File;
020: import java.io.FileInputStream;
021: import java.io.FileOutputStream;
022: import java.io.IOException;
023: import java.net.URL;
024: import java.nio.channels.FileChannel;
025: import java.util.ArrayList;
026: import java.util.List;
027:
028: import net.refractions.udig.catalog.ui.CatalogUIPlugin;
029: import net.refractions.udig.catalog.ui.internal.Messages;
030:
031: import org.eclipse.core.runtime.FileLocator;
032: import org.eclipse.core.runtime.IStatus;
033: import org.eclipse.core.runtime.Platform;
034: import org.eclipse.jface.dialogs.MessageDialog;
035: import org.eclipse.jface.preference.IPreferenceStore;
036: import org.eclipse.jface.preference.PreferencePage;
037: import org.eclipse.jface.resource.ImageDescriptor;
038: import org.eclipse.swt.SWT;
039: import org.eclipse.swt.events.ModifyListener;
040: import org.eclipse.swt.events.SelectionEvent;
041: import org.eclipse.swt.events.SelectionListener;
042: import org.eclipse.swt.graphics.Color;
043: import org.eclipse.swt.layout.GridData;
044: import org.eclipse.swt.layout.GridLayout;
045: import org.eclipse.swt.widgets.Button;
046: import org.eclipse.swt.widgets.Composite;
047: import org.eclipse.swt.widgets.Control;
048: import org.eclipse.swt.widgets.FileDialog;
049: import org.eclipse.swt.widgets.Label;
050: import org.eclipse.swt.widgets.Listener;
051: import org.eclipse.swt.widgets.Shell;
052: import org.eclipse.swt.widgets.Text;
053: import org.eclipse.ui.IWorkbench;
054: import org.eclipse.ui.PlatformUI;
055:
056: /**
057: * An abstract class that simplifies making a PreferencePage for obtaining a 3rd party proprietary jar required for a plugin.
058: *
059: * <p> An example of this is the Oracle Spatial JDBC Driver jar. It cannot be shipped with uDig because of licensing so it has
060: * a preference page that allows the user to easily install the jar into uDig</p>
061: *
062: * @see OracleSpatialPreferences
063: *
064: * @author Jesse
065: * @since 1.1.0
066: */
067: public abstract class AbstractProprietaryJarPreferencePage extends
068: PreferencePage {
069:
070: private Color red;
071: private Color black;
072: private Listener listener;
073: private Shell shell;
074: private UI[] ui;
075:
076: protected static class UI {
077: public String jar_name;
078: public Label label;
079: public Text input;
080: public Button browse;
081:
082: protected UI(String jar_name) {
083: this .jar_name = jar_name;
084: }
085: }
086:
087: /**
088: * @return
089: * @throws IOException
090: */
091: private File getFile(String name, boolean backup) {
092: URL url = getLibsURL();
093: if (url == null)
094: return new File(
095: "RandomCrazyPlaceholderlkjaljflkasdjfkjlkjasdfiwjkl"); //$NON-NLS-1$
096: URL localURL;
097: try {
098: localURL = FileLocator.toFileURL(url);
099: } catch (IOException e) {
100: return new File(
101: "RandomCrazyPlaceholderlkjaljflkasdjfkjlkjasdfiwjkl"); //$NON-NLS-1$
102: }
103: String prefix = backup ? "." : ""; //$NON-NLS-1$ //$NON-NLS-2$
104: File destDriver = new File(localURL.getFile() + prefix + name);
105: return destDriver;
106: }
107:
108: protected abstract URL getLibsURL();
109:
110: /**
111: * Returns true if the Correct driver is installed.
112: *
113: * @return
114: */
115: protected abstract boolean installed();
116:
117: protected Control createContents(Composite parent) {
118: this .shell = parent.getShell();
119: final Composite comp = new Composite(parent, SWT.NONE);
120: GridLayout layout = new GridLayout(3, false);
121: layout.marginBottom = 0;
122: layout.marginTop = 0;
123: layout.marginRight = 0;
124: layout.marginLeft = 0;
125: comp.setLayout(layout);
126:
127: ui = new UI[getRequiredJarsCount()];
128: List<Control> tablist = new ArrayList<Control>();
129:
130: for (int i = 0; i < ui.length; i++) {
131: ui[i] = createJDBCdriverUI(getDefaultJarName(i),
132: getDriverLabel(i), comp, null);
133: tablist.add(ui[i].input);
134: tablist.add(ui[i].browse);
135: }
136: comp.setTabList(tablist.toArray(new Control[0]));
137:
138: return comp;
139: }
140:
141: /**
142: * Returns the number of jars required to be imported.
143: *
144: * @return the number of jars required to be imported.
145: */
146: protected abstract int getRequiredJarsCount();
147:
148: /**
149: * The label beside the text area that indicates what type of file the user needs to add.
150: *
151: * @param jarIndex the jar input area being created.
152: * @see #getRequiredJarsCount()
153: *
154: * @return The label beside the text area that indicates what type of file the user needs to add.
155: */
156: protected abstract String getDriverLabel(int jarIndex);
157:
158: /**
159: * Returns a default name for the jar to import. It will appear in the text area as a hint to the user
160: * for what type of file they should be looking for.
161: *
162: * @param jarIndex the jar input area being created.
163: * @see #getRequiredJarsCount()
164: * @see #getDriverLabel(int)
165: * @return a default name for the jar to import.
166: */
167: protected abstract String getDefaultJarName(int jarIndex);
168:
169: public AbstractProprietaryJarPreferencePage() {
170: super ();
171: }
172:
173: /**
174: * @param comp
175: */
176: private UI createJDBCdriverUI(String jar_name, String label,
177: final Composite comp, Control above) {
178: final UI ui = new UI(jar_name);
179: ui.label = new Label(comp, SWT.FLAT);
180: ui.label.setText(label);
181: GridData layoutData = new GridData(SWT.LEFT, SWT.CENTER, false,
182: false);
183: ui.label.setLayoutData(layoutData);
184:
185: ui.input = new Text(comp, SWT.SINGLE | SWT.BORDER);
186: ui.input.addModifyListener(new ModifyListener() {
187: public void modifyText(org.eclipse.swt.events.ModifyEvent e) {
188: File srcDriver = new File(ui.input.getText());
189: if (installed())
190: acceptance(
191: Messages.DependencyQueryPreferencePage_fileExists,
192: ui.input);
193: else if (!srcDriver.exists())
194: error(
195: Messages.DependencyQueryPreferencePage_fileNotFound,
196: ui.input);
197: else
198: error(
199: Messages.DependencyQueryPreferencePage_notValid,
200: ui.input);
201:
202: };
203: });
204: String storedValue = getPreferenceStore()
205: .getString(ui.jar_name);
206: if (storedValue.trim().length() == 0) {
207: storedValue = null;
208: }
209: ui.input.setText(storedValue == null ? ui.jar_name
210: : storedValue);
211: layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false);
212: ui.input.setLayoutData(layoutData);
213:
214: ui.browse = new Button(comp, SWT.PUSH);
215: ui.browse
216: .setText(Messages.DependencyQueryPreferencePage_browse);
217:
218: ui.browse.addSelectionListener(new SelectionListener() {
219:
220: public void widgetSelected(SelectionEvent e) {
221: widgetDefaultSelected(e);
222: }
223:
224: public void widgetDefaultSelected(SelectionEvent e) {
225: FileDialog fileDialog = new FileDialog(comp.getShell(),
226: SWT.OPEN);
227: fileDialog
228: .setFilterExtensions(new String[] { "*.jar" }); //$NON-NLS-1$
229: fileDialog
230: .setFilterNames(new String[] { Messages.DependencyQueryPreferencePage_archive });
231: String result = fileDialog.open();
232: if (result != null)
233: ui.input.setText(result);
234: }
235:
236: });
237:
238: layoutData = new GridData(SWT.RIGHT, SWT.CENTER, false, false);
239: ui.browse.setLayoutData(layoutData);
240:
241: return ui;
242: }
243:
244: public void performDefaults() {
245: for (UI ui : this .ui) {
246: if (ui.input != null)
247: ui.input.setText(ui.jar_name);
248: }
249: super .performDefaults();
250:
251: if (listener != null)
252: listener.handleEvent(null);
253: }
254:
255: public boolean performOk() {
256: for (UI current : this .ui) {
257: if (current.input.getText().trim().length() > 0) {
258: File srcDriver = null;
259: try {
260: srcDriver = new File(current.input.getText());
261: if (!srcDriver.exists()) {
262: if (current.input.getText().equals(
263: current.jar_name))
264: return true;
265: error(
266: Messages.DependencyQueryPreferencePage_fileNotFound,
267: current.input);
268: return false;
269: }
270: } catch (Exception e) {
271: error(
272: Messages.DependencyQueryPreferencePage_copyError,
273: current.input);
274: return false;
275: }
276: try {
277: File destDriver = getFile(current.jar_name, false);
278: if (destDriver != null) {
279: renameFile(destDriver,
280: "." + destDriver.getName(), false); //$NON-NLS-1$
281: destDriver.createNewFile();
282: copyfile(srcDriver, destDriver);
283: }
284: } catch (Exception e) {
285: error(
286: Messages.DependencyQueryPreferencePage_copyError,
287: current.input);
288: return false;
289: }
290: getPreferenceStore().putValue(current.jar_name,
291: current.input.getText());
292: }
293: }
294:
295: if (listener != null)
296: listener.handleEvent(null);
297:
298: boolean restart = MessageDialog
299: .openQuestion(
300: getShell(),
301: Messages.DependencyQueryPreferencePage_restartTitle,
302: Messages.DependencyQueryPreferencePage_restartNeeded
303: + Messages.DependencyQueryPreferencePage_restartQuestion);
304: if (restart) {
305: PlatformUI.getWorkbench().restart();
306: }
307:
308: return true;
309: }
310:
311: @Override
312: public Shell getShell() {
313: return shell;
314: }
315:
316: public AbstractProprietaryJarPreferencePage(String title) {
317: super (title);
318: }
319:
320: /**
321: * @param flag
322: */
323: private void renameFile(File flag, String newname,
324: boolean deleteOnFail) {
325: if (flag != null) {
326: File dest = new File(flag.getParentFile(), newname);
327:
328: try {
329: if (dest.exists())
330: dest.delete();
331: flag.renameTo(dest);
332: } catch (Exception e) {
333: try {
334: copyfile(flag, dest);
335: } catch (IOException e1) {
336: CatalogUIPlugin.log("error renaming flag", e1); //$NON-NLS-1$
337: if (deleteOnFail) {
338: flag.delete();
339: }
340: }
341: }
342: }
343: }
344:
345: private void copyfile(File src, File dest) throws IOException {
346: FileChannel srcChannel = null;
347: FileChannel dstChannel = null;
348: FileInputStream fileInputStream = null;
349: FileOutputStream fileOutputStream = null;
350: try {
351: fileInputStream = new FileInputStream(src);
352: fileOutputStream = new FileOutputStream(dest);
353: // Create channel on the source
354: srcChannel = fileInputStream.getChannel();
355:
356: // Create channel on the destination
357: dstChannel = fileOutputStream.getChannel();
358:
359: // Copy file contents from source to destination
360: dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
361: } finally {
362: // Close the channels
363: try {
364: if (fileInputStream != null)
365: fileInputStream.close();
366: } catch (IOException e) {
367: CatalogUIPlugin.log("", e); //$NON-NLS-1$
368: }
369: try {
370: if (fileOutputStream != null)
371: fileOutputStream.close();
372: } catch (IOException e) {
373: CatalogUIPlugin.log("", e); //$NON-NLS-1$
374: }
375: try {
376: if (srcChannel != null)
377: srcChannel.close();
378: } catch (IOException e) {
379: CatalogUIPlugin.log("", e); //$NON-NLS-1$
380: }
381: try {
382: if (dstChannel != null)
383: dstChannel.close();
384: } catch (IOException e) {
385: CatalogUIPlugin.log("", e); //$NON-NLS-1$
386: }
387: }
388: }
389:
390: private void error(String message, Text field) {
391: setMessage(message, IStatus.WARNING);
392: field.setForeground(getRed());
393: field.setToolTipText(message);
394: }
395:
396: private void acceptance(String message, Text field) {
397: setMessage(null, IStatus.WARNING);
398: field.setForeground(getBlack());
399: field.setToolTipText(message);
400: }
401:
402: private Color getRed() {
403: if (red == null)
404: red = new Color(getShell().getDisplay(), 255, 0, 0);
405: return red;
406: }
407:
408: private Color getBlack() {
409: if (black == null)
410: black = new Color(getShell().getDisplay(), 0, 0, 0);
411: return black;
412: }
413:
414: public void dispose() {
415: super .dispose();
416: if (red != null) {
417: red.dispose();
418: red = null;
419: }
420: if (black != null) {
421: black.dispose();
422: black = null;
423: }
424: }
425:
426: public void init(IWorkbench workbench) {
427: }
428:
429: public void setListener(Listener listener) {
430: this .listener = listener;
431: }
432:
433: @Override
434: protected IPreferenceStore doGetPreferenceStore() {
435: return PlatformUI.getPreferenceStore();
436: }
437:
438: public AbstractProprietaryJarPreferencePage(String title,
439: ImageDescriptor desc) {
440: super(title, desc);
441: }
442:
443: }
|