/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at legal-notices/CDDLv1_0.txt. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2008-2010 Sun Microsystems, Inc. * Portions Copyright 2012-2015 ForgeRock AS */ package org.opends.guitools.controlpanel.ui; import static org.opends.messages.AdminToolMessages.*; import java.awt.Component; import java.awt.GridBagConstraints; import java.awt.Point; import java.io.IOException; import java.io.StringReader; import java.util.List; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.tree.TreePath; import org.forgerock.i18n.LocalizableMessage; import org.opends.guitools.controlpanel.datamodel.CustomSearchResult; import org.opends.guitools.controlpanel.task.OfflineUpdateException; import org.opends.guitools.controlpanel.util.Utilities; import org.opends.server.types.Entry; import org.opends.server.types.LDIFImportConfig; import org.opends.server.types.OpenDsException; import org.opends.server.util.Base64; import org.opends.server.util.LDIFReader; import org.opends.server.util.StaticUtils; /** * The panel displaying an LDIF view of an entry. */ public class LDIFViewEntryPanel extends ViewEntryPanel { /** Callback that sets the viewport's view position. */ private static final class SetViewPosition implements Runnable { private final Point p; private final JScrollPane scroll; private SetViewPosition(JScrollPane scroll, Point p) { this.p = p; this.scroll = scroll; } /** {@inheritDoc} */ @Override public void run() { if (p != null && scroll.getViewport().contains(p)) { scroll.getViewport().setViewPosition(p); } } } private static final long serialVersionUID = 2775960608128921072L; private JScrollPane editableScroll; private JScrollPane readOnlyScroll; private JTextArea editableAttributes; private JTextArea readOnlyAttributes; private CustomSearchResult searchResult; /** Default constructor. */ public LDIFViewEntryPanel() { createLayout(); } /** {@inheritDoc} */ @Override public Component getPreferredFocusComponent() { return editableAttributes; } /** * Creates the layout of the panel (but the contents are not populated here). */ private void createLayout() { GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 1; gbc.fill = GridBagConstraints.NONE; gbc.anchor = GridBagConstraints.WEST; gbc.weightx = 1.0; addTitlePanel(this, gbc); gbc.gridy ++; gbc.insets.top = 10; editableAttributes = Utilities.createTextArea(LocalizableMessage.EMPTY, 20, 30); editableAttributes.getDocument().addDocumentListener(new DocumentListener() { @Override public void insertUpdate(DocumentEvent ev) { notifyListeners(); } @Override public void changedUpdate(DocumentEvent ev) { notifyListeners(); } @Override public void removeUpdate(DocumentEvent ev) { notifyListeners(); } }); gbc.weighty = 0.6; gbc.fill = GridBagConstraints.BOTH; gbc.gridy ++; editableScroll = Utilities.createScrollPane(editableAttributes); add(editableScroll, gbc); gbc.weighty = 0.0; gbc.insets.top = 10; JLabel lReadOnly = Utilities.createPrimaryLabel( INFO_CTRL_PANEL_NON_EDITABLE_ATTRIBUTES.get()); gbc.gridy ++; add(lReadOnly, gbc); gbc.insets.top = 5; readOnlyAttributes = Utilities.createNonEditableTextArea(LocalizableMessage.EMPTY, 10, 30); gbc.weightx = 1.0; gbc.weighty = 0.4; gbc.fill = GridBagConstraints.BOTH; gbc.gridy ++; readOnlyScroll = Utilities.createScrollPane(readOnlyAttributes); add(readOnlyScroll, gbc); } /** {@inheritDoc} */ @Override public void update(CustomSearchResult sr, boolean isReadOnly, TreePath path) { boolean sameEntry = false; if (searchResult != null && sr != null) { sameEntry = searchResult.getDN().equals(sr.getDN()); } searchResult = sr; updateTitle(sr, path); StringBuilder sb = new StringBuilder(); sb.append("dn: ").append(sr.getDN()); if (isReadOnly) { editableScroll.setVisible(false); for (String attrName : sr.getAttributeNames()) { List<Object> values = sr.getAttributeValues(attrName); for (Object o : values) { sb.append("\n").append(getLDIFLine(attrName, o)); } } final Point p1 = sameEntry ? readOnlyScroll.getViewport().getViewPosition() : new Point(0, 0); readOnlyAttributes.setText(sb.toString()); SwingUtilities.invokeLater(new SetViewPosition(readOnlyScroll, p1)); } else { editableScroll.setVisible(true); for (String attrName : sr.getAttributeNames()) { if (!schemaReadOnlyAttributesLowerCase.contains(attrName.toLowerCase())) { List<Object> values = sr.getAttributeValues(attrName); for (Object o : values) { sb.append("\n").append(getLDIFLine(attrName, o)); } } } final Point p1 = sameEntry ? editableScroll.getViewport().getViewPosition() : new Point(0, 0); ignoreEntryChangeEvents = true; editableAttributes.setText(sb.toString()); ignoreEntryChangeEvents = false; SwingUtilities.invokeLater(new SetViewPosition(editableScroll, p1)); // Read-only attributes boolean oneLineAdded = false; sb = new StringBuilder(); for (String attrName : schemaReadOnlyAttributes) { List<Object> values = sr.getAttributeValues(attrName); for (Object o : values) { if (oneLineAdded) { sb.append("\n"); } oneLineAdded = true; sb.append(getLDIFLine(attrName, o)); } } final Point p2 = sameEntry ? readOnlyScroll.getViewport().getViewPosition() : new Point(0, 0); readOnlyAttributes.setText(sb.toString()); SwingUtilities.invokeLater(new SetViewPosition(readOnlyScroll, p2)); } } /** {@inheritDoc} */ @Override public GenericDialog.ButtonType getButtonType() { return GenericDialog.ButtonType.NO_BUTTON; } /** {@inheritDoc} */ @Override protected String getDisplayedDN() { String dn = null; // Do it fast, this is called to update the dn displayed in the title. String ldif = getLDIF(); int index = ldif.toLowerCase().indexOf("dn: "); if (index != -1) { int index2 = ldif.indexOf("\n", index); if (index2 != -1) { dn = ldif.substring(index + 3, index2).trim(); } } return dn; } /** {@inheritDoc} */ @Override protected List<Object> getValues(String attrName) { throw new IllegalStateException("This method should not be called."); } /** {@inheritDoc} */ @Override public Entry getEntry() throws OpenDsException { LDIFImportConfig ldifImportConfig = null; try { String ldif = getLDIF(); ldifImportConfig = new LDIFImportConfig(new StringReader(ldif)); LDIFReader reader = new LDIFReader(ldifImportConfig); Entry entry = reader.readEntry(checkSchema()); addValuesInRDN(entry); return entry; } catch (IOException ioe) { throw new OfflineUpdateException( ERR_CTRL_PANEL_ERROR_CHECKING_ENTRY.get(ioe), ioe); } finally { if (ldifImportConfig != null) { ldifImportConfig.close(); } } } /** * Returns the LDIF representation of the entry, only returns the editable * attributes. * @return the LDIF representation of the entry. */ private String getLDIF() { return editableAttributes.getText(); } /** * Returns the equivalent LDIF line for a given attribute and value. * @param attrName the attribute name. * @param o the value. * @return the equivalent LDIF line for the provided attribute and value. */ private String getLDIFLine(String attrName, Object o) { String attrValue; if (o instanceof String) { if (Utilities.hasControlCharaters((String)o)) { attrValue = Base64.encode(StaticUtils.getBytes((String)o)); attrName = attrName+":"; } else { attrValue = (String)o; } } else if (o instanceof byte[]) { attrValue = Base64.encode((byte[])o); // To indicate that is base64 encoded attrName = attrName+":"; } else { attrValue = String.valueOf(o); } return attrName+": "+ attrValue; } }