001: /* uDig - User Friendly Desktop Internet GIS client
002: * http://udig.refractions.net
003: * (C) 2004, Refractions Research Inc.
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation;
008: * version 2.1 of the License.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: */
015: package net.refractions.udig.internal.ui;
016:
017: import java.io.BufferedReader;
018: import java.io.File;
019: import java.io.FileReader;
020: import java.io.IOException;
021: import java.io.OutputStream;
022: import java.lang.reflect.InvocationTargetException;
023: import java.net.HttpURLConnection;
024: import java.net.URL;
025: import java.net.URLEncoder;
026:
027: import net.refractions.udig.ui.PlatformGIS;
028: import net.refractions.udig.ui.internal.Messages;
029:
030: import org.eclipse.core.runtime.IProgressMonitor;
031: import org.eclipse.core.runtime.Platform;
032: import org.eclipse.jface.dialogs.IDialogConstants;
033: import org.eclipse.jface.dialogs.IMessageProvider;
034: import org.eclipse.jface.dialogs.TitleAreaDialog;
035: import org.eclipse.jface.operation.IRunnableWithProgress;
036: import org.eclipse.jface.resource.ImageDescriptor;
037: import org.eclipse.swt.SWT;
038: import org.eclipse.swt.events.ModifyEvent;
039: import org.eclipse.swt.events.ModifyListener;
040: import org.eclipse.swt.graphics.Point;
041: import org.eclipse.swt.layout.GridData;
042: import org.eclipse.swt.layout.GridLayout;
043: import org.eclipse.swt.widgets.Button;
044: import org.eclipse.swt.widgets.Composite;
045: import org.eclipse.swt.widgets.Control;
046: import org.eclipse.swt.widgets.Label;
047: import org.eclipse.swt.widgets.Shell;
048: import org.eclipse.swt.widgets.Text;
049:
050: /**
051: * Dialog for sending the error log to the development team.
052: *
053: * @author chorner
054: */
055: public class SendLogDialog extends TitleAreaDialog {
056:
057: private Label contactLabel;
058: private Text contact;
059: private Label noteLabel;
060: private Text notes;
061: private Label logLabel;
062: private Text log;
063:
064: boolean hasLog = false;
065:
066: protected SendLogDialog(Shell parentShell) {
067: super (parentShell);
068: setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE
069: | SWT.APPLICATION_MODAL | getDefaultOrientation());
070: }
071:
072: @Override
073: protected void configureShell(Shell newShell) {
074: super .configureShell(newShell);
075: newShell.setText(Messages.SendLogDialog_title);
076: }
077:
078: @Override
079: protected Point getInitialSize() {
080: return new Point(450, 350);
081: }
082:
083: @Override
084: protected Control createDialogArea(Composite parent) {
085: setTitle(Messages.SendLogDialog_description);
086: ImageDescriptor image = Images
087: .getDescriptor(ImageConstants.LOG_WIZ);
088: if (image != null)
089: setTitleImage(image.createImage());
090:
091: // create a composite with standard margins and spacing
092: Composite composite = new Composite(parent, SWT.RESIZE);
093: GridLayout layout = new GridLayout(2, false);
094: layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
095: layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
096: layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
097: layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
098: composite.setLayout(layout);
099: composite.setLayoutData(new GridData(GridData.FILL_BOTH));
100: applyDialogFont(composite);
101:
102: contactLabel = new Label(composite, SWT.NONE);
103: contactLabel.setLayoutData(new GridData(SWT.NONE, SWT.NONE,
104: false, false));
105: contactLabel.setText(Messages.SendLogDialog_contact);
106:
107: contact = new Text(composite, SWT.BORDER);
108: GridData gridData = new GridData(SWT.FILL, SWT.FILL, true,
109: false);
110: gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
111: gridData.horizontalSpan = 2;
112: contact.setLayoutData(gridData);
113: contact.addModifyListener(new ModifyListener() {
114:
115: public void modifyText(ModifyEvent e) {
116: refreshButtons();
117: }
118:
119: });
120:
121: noteLabel = new Label(composite, SWT.NONE);
122: noteLabel.setLayoutData(new GridData(SWT.NONE, SWT.NONE, false,
123: false));
124: noteLabel.setText(Messages.SendLogDialog_notes);
125:
126: notes = new Text(composite, SWT.WRAP | SWT.BORDER | SWT.MULTI);
127: gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
128: gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
129: gridData.heightHint = notes.getLineHeight() * 2;
130: gridData.horizontalSpan = 2;
131: notes.setLayoutData(gridData);
132: notes.addModifyListener(new ModifyListener() {
133:
134: public void modifyText(ModifyEvent e) {
135: refreshButtons();
136: }
137:
138: });
139:
140: logLabel = new Label(composite, SWT.NONE);
141: gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
142: gridData.verticalAlignment = SWT.END;
143: logLabel.setLayoutData(gridData);
144: logLabel.setText(Messages.SendLogDialog_log);
145:
146: log = new Text(composite, SWT.WRAP | SWT.READ_ONLY | SWT.BORDER
147: | SWT.V_SCROLL | SWT.MULTI);
148: log.setBackground(getShell().getDisplay().getSystemColor(
149: SWT.COLOR_WIDGET_BACKGROUND));
150: gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
151: gridData.horizontalSpan = 2;
152: log.setLayoutData(gridData);
153: log.setText(Messages.SendLogDialog_reading);
154: log.setEnabled(false);
155:
156: //start a thread to acquire the log file
157: PopulateLogRunnable populateLog = new PopulateLogRunnable();
158: PlatformGIS.run(populateLog);
159: contact.setFocus();
160:
161: return composite;
162: }
163:
164: @Override
165: protected void createButtonsForButtonBar(Composite parent) {
166: createButton(parent, IDialogConstants.PROCEED_ID,
167: Messages.SendLogDialog_submit, false);
168: createButton(parent, IDialogConstants.CANCEL_ID,
169: IDialogConstants.CANCEL_LABEL, false);
170: refreshButtons();
171: }
172:
173: private void refreshButtons() {
174: boolean hasContact = false;
175: boolean hasNote = false;
176: if (notes.getText() != null && notes.getText().length() > 0) {
177: hasNote = true;
178: }
179: if (contact.getText() != null && contact.getText().length() > 0) {
180: hasContact = true;
181: }
182: Button proceed = getButton(IDialogConstants.PROCEED_ID);
183: if (hasContact && hasNote) {
184: setMessage(null);
185: proceed.setEnabled(hasLog); //only allow submission if a log exists
186: } else if (!hasContact) {
187: setMessage(Messages.SendLogDialog_contact_message,
188: IMessageProvider.WARNING);
189: proceed.setEnabled(false);
190: } else {
191: setMessage(Messages.SendLogDialog_notes_message,
192: IMessageProvider.WARNING);
193: proceed.setEnabled(false);
194: }
195:
196: }
197:
198: @Override
199: protected void buttonPressed(int buttonId) {
200: if (IDialogConstants.PROCEED_ID == buttonId) {
201: try {
202: sendLog();
203: } catch (RuntimeException e) {
204: throw (RuntimeException) new RuntimeException()
205: .initCause(e);
206: } finally {
207: okPressed();
208: }
209: }
210: if (buttonId == IDialogConstants.CANCEL_ID) {
211: okPressed();
212: }
213: }
214:
215: private void sendLog() {
216: try {
217: URL url = new URL(
218: "http://udig.refractions.net/errorlog.php"); //$NON-NLS-1$
219: HttpURLConnection connection = (HttpURLConnection) url
220: .openConnection();
221: connection.setRequestMethod("POST"); //$NON-NLS-1$
222: connection.setDoOutput(true);
223: connection
224: .setRequestProperty(
225: "Content-type", "application/x-www-form-urlencoded"); //$NON-NLS-1$ //$NON-NLS-2$
226: connection.setDoInput(true);
227:
228: StringBuilder text = new StringBuilder();
229: text.append("Contact:\r\n"); //$NON-NLS-1$
230: text.append(contact.getText());
231: text.append("\r\n\r\nUser comments:\r\n"); //$NON-NLS-1$
232: text.append(notes.getText());
233: text.append("\r\n\r\nSystem Info:\r\n"); //$NON-NLS-1$
234: text.append(getSystemInfo());
235: text.append("\r\n----\r\n\r\n"); //$NON-NLS-1$
236: text.append(log.getText());
237: text.append("\r\n"); //$NON-NLS-1$
238: String body = "body=" + URLEncoder.encode(text.toString(), "UTF-8"); //$NON-NLS-1$//$NON-NLS-2$
239:
240: OutputStream outStream;
241: outStream = connection.getOutputStream();
242: outStream.write(body.getBytes());
243: outStream.flush();
244: outStream.close();
245:
246: connection.getResponseCode();
247: } catch (Exception e) {
248: UiPlugin.log("Error log submission failed", e); //$NON-NLS-1$
249: } finally {
250: UiPlugin
251: .log(
252: "Log submitted, chars: " + log.getText().length(), null); //$NON-NLS-1$
253: }
254: }
255:
256: public static boolean logExists() {
257: String filename = Platform.getLogFileLocation().toOSString();
258: File log = new File(filename);
259: return log.exists();
260: }
261:
262: private String getSystemInfo() {
263: StringBuilder content = new StringBuilder();
264: //udig version number
265: content.append("uDig "); //$NON-NLS-1$
266: content.append(UiPlugin.getDefault().getVersion());
267: return content.toString();
268: }
269:
270: private String getLogText(IProgressMonitor monitor) {
271: String filename = Platform.getLogFileLocation().toOSString();
272: File file = new File(filename);
273: FileReader in = null;
274: BufferedReader br = null;
275: try {
276: StringBuilder content = new StringBuilder();
277: in = new FileReader(file);
278: br = new BufferedReader(in);
279: String line;
280: while ((line = br.readLine()) != null) {
281: content.append(line);
282: content.append("\n"); //$NON-NLS-1$
283: }
284: return content.toString();
285: } catch (IOException e) {
286: return null;
287: } finally {
288: try {
289: if (br != null)
290: br.close();
291: if (in != null)
292: in.close();
293: } catch (IOException e) {
294: }
295: }
296: }
297:
298: private class PopulateLogRunnable implements IRunnableWithProgress {
299:
300: public void run(IProgressMonitor monitor)
301: throws InvocationTargetException, InterruptedException {
302: String text;
303: if (logExists()) {
304: text = getLogText(monitor);
305: } else {
306: text = Messages.SendLogDialog_empty;
307: }
308:
309: if (monitor.isCanceled()) {
310: //freak out
311: throw new InterruptedException(
312: "Log acquisition was canceled."); //$NON-NLS-1$
313: } else {
314: //update dialog contents, mark log as acquired
315: final String logText = text;
316: PlatformGIS.syncInDisplayThread(new Runnable() {
317:
318: public void run() {
319: log.setText(logText);
320: log.setEnabled(true);
321: hasLog = true;
322: refreshButtons();
323: }
324:
325: });
326: }
327: }
328: }
329:
330: }
|