Java tutorial
/* * Copyright 2012 - 2015 Manuel Laggner * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.tinymediamanager.ui.dialogs; import java.awt.Cursor; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FilenameFilter; import java.io.IOException; import java.util.Properties; import java.util.ResourceBundle; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.JTextPane; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.tinymediamanager.Globals; import org.tinymediamanager.ReleaseInfo; import org.tinymediamanager.core.License; import org.tinymediamanager.core.Settings; import org.tinymediamanager.scraper.http.TmmHttpClient; import org.tinymediamanager.ui.EqualsLayout; import org.tinymediamanager.ui.IconManager; import org.tinymediamanager.ui.UTF8Control; import com.jgoodies.forms.layout.ColumnSpec; import com.jgoodies.forms.layout.FormLayout; import com.jgoodies.forms.layout.FormSpecs; import com.jgoodies.forms.layout.RowSpec; import com.squareup.okhttp.Headers; import com.squareup.okhttp.MultipartBuilder; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; import com.squareup.okhttp.RequestBody; /** * The Class BugReportDialog, to send bug reports directly from inside tmm. * * @author Manuel Laggner */ public class BugReportDialog extends TmmDialog { private static final long serialVersionUID = 1992385114573899815L; /** * @wbp.nls.resourceBundle messages */ private static final ResourceBundle BUNDLE = ResourceBundle.getBundle("messages", new UTF8Control()); //$NON-NLS-1$ private static final Logger LOGGER = LoggerFactory.getLogger(BugReportDialog.class); private JTextField tfName; private JTextArea textArea; private JTextField tfEmail; /** * Instantiates a new feedback dialog. */ public BugReportDialog() { super(BUNDLE.getString("BugReport"), "bugReport"); //$NON-NLS-1$ setBounds(100, 100, 600, 470); getContentPane().setLayout(new FormLayout( new ColumnSpec[] { FormSpecs.RELATED_GAP_COLSPEC, ColumnSpec.decode("max(400px;min):grow"), FormSpecs.RELATED_GAP_COLSPEC, }, new RowSpec[] { FormSpecs.RELATED_GAP_ROWSPEC, RowSpec.decode("default:grow"), FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC, FormSpecs.RELATED_GAP_ROWSPEC, })); JPanel panelContent = new JPanel(); getContentPane().add(panelContent, "2, 2, fill, fill"); panelContent.setLayout(new FormLayout( new ColumnSpec[] { FormSpecs.RELATED_GAP_COLSPEC, FormSpecs.DEFAULT_COLSPEC, FormSpecs.RELATED_GAP_COLSPEC, ColumnSpec.decode("250dlu:grow"), FormSpecs.RELATED_GAP_COLSPEC, }, new RowSpec[] { FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC, FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC, FormSpecs.PARAGRAPH_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC, FormSpecs.LABEL_COMPONENT_GAP_ROWSPEC, RowSpec.decode("50dlu:grow"), FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC, FormSpecs.PARAGRAPH_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC, FormSpecs.RELATED_GAP_ROWSPEC, })); JLabel lblName = new JLabel(BUNDLE.getString("BugReport.name")); //$NON-NLS-1$ panelContent.add(lblName, "2, 2, right, default"); tfName = new JTextField(); panelContent.add(tfName, "4, 2, fill, default"); tfName.setColumns(10); JLabel lblEmail = new JLabel(BUNDLE.getString("BugReport.email")); //$NON-NLS-1$ panelContent.add(lblEmail, "2, 4, right, default"); tfEmail = new JTextField(); panelContent.add(tfEmail, "4, 4, fill, default"); // pre-fill dialog if (Globals.isDonator()) { Properties p = License.decrypt(); tfEmail.setText(p.getProperty("email")); tfName.setText(p.getProperty("user")); } JLabel lblEmaildesc = new JLabel(BUNDLE.getString("BugReport.email.description")); //$NON-NLS-1$ panelContent.add(lblEmaildesc, "2, 5, 3, 1"); JLabel lblFeedback = new JLabel(BUNDLE.getString("BugReport.description")); //$NON-NLS-1$ panelContent.add(lblFeedback, "2, 7, 3, 1"); JScrollPane scrollPane = new JScrollPane(); panelContent.add(scrollPane, "2, 9, 3, 1, fill, fill"); textArea = new JTextArea(); scrollPane.setViewportView(textArea); textArea.setLineWrap(true); textArea.setWrapStyleWord(true); JTextPane textPane = new JTextPane(); textPane.setText(BUNDLE.getString("BugReport.hint"));//$NON-NLS-1$ textPane.setOpaque(false); panelContent.add(textPane, "2, 11, 3, 1, fill, fill"); final JLabel lblHintImage = new JLabel(IconManager.INFO); panelContent.add(lblHintImage, "2, 13"); final JTextPane tpHint = new JTextPane(); tpHint.setOpaque(false); tpHint.setText(BUNDLE.getString("BugReport.hint2"));//$NON-NLS-1$ panelContent.add(tpHint, "4, 13, fill, fill"); JPanel panelButtons = new JPanel(); panelButtons.setLayout(new EqualsLayout(5)); getContentPane().add(panelButtons, "2, 4, fill, fill"); JButton btnSend = new JButton(BUNDLE.getString("BugReport.send")); //$NON-NLS-1$ btnSend.setIcon(IconManager.APPLY); btnSend.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { // check if feedback is provided if (StringUtils.isEmpty(textArea.getText())) { JOptionPane.showMessageDialog(null, BUNDLE.getString("BugReport.description.empty")); //$NON-NLS-1$ return; } // send bug report try { sendBugReport(); } catch (Exception e) { LOGGER.error("failed sending bug report: " + e.getMessage()); JOptionPane.showMessageDialog(null, BUNDLE.getObject("BugReport.send.error") + "\n" + e.getMessage()); //$NON-NLS-1$ return; } BugReportDialog.this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); JOptionPane.showMessageDialog(null, BUNDLE.getObject("BugReport.send.ok")); //$NON-NLS-1$ setVisible(false); } }); panelButtons.add(btnSend); JButton btnCacnel = new JButton(BUNDLE.getString("Button.cancel")); //$NON-NLS-1$ btnCacnel.setIcon(IconManager.CANCEL); btnCacnel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { setVisible(false); } }); panelButtons.add(btnCacnel); } private void sendBugReport() throws Exception { OkHttpClient client = TmmHttpClient.getHttpClient(); String url = "https://script.google.com/macros/s/AKfycbzrhTmZiHJb1bdCqyeiVOqLup8zK4Dbx6kAtHYsgzBVqHTaNJqj/exec"; StringBuilder message = new StringBuilder("Bug report from "); message.append(tfName.getText()); message.append("\nEmail:"); message.append(tfEmail.getText()); message.append("\n"); message.append("\nis Donator?: "); message.append(Globals.isDonator()); message.append("\nVersion: "); message.append(ReleaseInfo.getRealVersion()); message.append("\nBuild: "); message.append(ReleaseInfo.getRealBuildDate()); message.append("\nOS: "); message.append(System.getProperty("os.name")); message.append(" "); message.append(System.getProperty("os.version")); message.append("\nJDK: "); message.append(System.getProperty("java.version")); message.append(" "); message.append(System.getProperty("java.vendor")); message.append("\nUUID: "); message.append(System.getProperty("tmm.uuid")); message.append("\n\n"); message.append(textArea.getText()); BugReportDialog.this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); MultipartBuilder multipartBuilder = new MultipartBuilder(); multipartBuilder.type(MultipartBuilder.FORM); multipartBuilder.addPart(Headers.of("Content-Disposition", "form-data; name=\"message\""), RequestBody.create(null, message.toString())); multipartBuilder.addPart(Headers.of("Content-Disposition", "form-data; name=\"sender\""), RequestBody.create(null, tfEmail.getText())); // attach files try { // build zip with selected files in it ByteArrayOutputStream os = new ByteArrayOutputStream(); ZipOutputStream zos = new ZipOutputStream(os); // attach logs File[] logs = new File("logs").listFiles(new FilenameFilter() { Pattern logPattern = Pattern.compile("tmm\\.log\\.*"); @Override public boolean accept(File directory, String filename) { Matcher matcher = logPattern.matcher(filename); if (matcher.find()) { return true; } return false; } }); if (logs != null) { for (File logFile : logs) { try { FileInputStream in = new FileInputStream(logFile); ZipEntry ze = new ZipEntry(logFile.getName()); zos.putNextEntry(ze); IOUtils.copy(in, zos); in.close(); zos.closeEntry(); } catch (Exception e) { LOGGER.warn("unable to attach " + logFile.getName() + ": " + e.getMessage()); } } } try { FileInputStream in = new FileInputStream("launcher.log"); ZipEntry ze = new ZipEntry("launcher.log"); zos.putNextEntry(ze); IOUtils.copy(in, zos); in.close(); zos.closeEntry(); } catch (Exception e) { LOGGER.warn("unable to attach launcher.log: " + e.getMessage()); } // attach config file try { ZipEntry ze = new ZipEntry("config.xml"); zos.putNextEntry(ze); FileInputStream in = new FileInputStream( new File(Settings.getInstance().getSettingsFolder(), "config.xml")); IOUtils.copy(in, zos); in.close(); zos.closeEntry(); } catch (Exception e) { LOGGER.warn("unable to attach config.xml: " + e.getMessage()); } zos.close(); byte[] data = os.toByteArray(); String data_string = Base64.encodeBase64String(data); multipartBuilder.addPart(Headers.of("Content-Disposition", "form-data; name=\"logs\""), RequestBody.create(null, data_string)); } catch (IOException ex) { LOGGER.warn("error adding attachments", ex); } Request request = new Request.Builder().url(url).post(multipartBuilder.build()).build(); client.newCall(request).execute(); } @Override public void pack() { // pack will mess this dialog up } }