/* * The contents of this file are subject to the terms of the Common Development and * Distribution License (the License). You may not use this file except in compliance with the * License. * * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the * specific language governing permission and limitations under the License. * * When distributing Covered Software, include this CDDL Header Notice in each file and include * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL * Header, with the fields enclosed by brackets [] replaced by your own identifying * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2008-2010 Sun Microsystems, Inc. * Portions Copyright 2012-2016 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.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.forgerock.opendj.ldap.Attribute; import org.forgerock.opendj.ldap.ByteString; import org.forgerock.opendj.ldap.Entry; import org.forgerock.opendj.ldif.LDIFEntryReader; import org.opends.guitools.controlpanel.task.OfflineUpdateException; import org.opends.guitools.controlpanel.util.Utilities; import org.opends.server.types.OpenDsException; /** 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; } @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 Entry searchResult; /** Default constructor. */ public LDIFViewEntryPanel() { createLayout(); } @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); } @Override public void update(Entry sr, boolean isReadOnly, TreePath path) { boolean sameEntry = false; if (searchResult != null && sr != null) { sameEntry = searchResult.getName().equals(sr.getName()); } searchResult = sr; updateTitle(sr, path); StringBuilder sb = new StringBuilder(); sb.append("dn: ").append(sr.getName()); if (isReadOnly) { editableScroll.setVisible(false); for (Attribute attr : sr.getAllAttributes()) { final String attrName = attr.getAttributeDescriptionAsString(); for (ByteString v : attr) { sb.append("\n").append(getLDIFLine(attrName, v)); } } 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 (Attribute attr : sr.getAllAttributes()) { String attrName = attr.getAttributeDescriptionAsString(); if (!schemaReadOnlyAttributesLowerCase.contains(attrName.toLowerCase())) { for (ByteString v : attr) { sb.append("\n").append(getLDIFLine(attrName, v)); } } } 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) { Attribute attr = sr.getAttribute(attrName); if (attr != null) { for (ByteString v : attr) { if (oneLineAdded) { sb.append("\n"); } oneLineAdded = true; sb.append(getLDIFLine(attrName, v)); } } } final Point p2 = sameEntry ? readOnlyScroll.getViewport().getViewPosition() : new Point(0, 0); readOnlyAttributes.setText(sb.toString()); SwingUtilities.invokeLater(new SetViewPosition(readOnlyScroll, p2)); } } @Override public GenericDialog.ButtonType getButtonType() { return GenericDialog.ButtonType.NO_BUTTON; } @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; } @Override protected List getValues(String attrName) { throw new IllegalStateException("This method should not be called."); } @Override public Entry getEntry() throws OpenDsException { String ldif = getLDIF(); try (LDIFEntryReader reader = new LDIFEntryReader(ldif)) { Entry entry = reader.readEntry(); addValuesInRDN(entry); return entry; } catch (IOException ioe) { throw new OfflineUpdateException( ERR_CTRL_PANEL_ERROR_CHECKING_ENTRY.get(ioe), ioe); } } /** * 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 value the value. * @return the equivalent LDIF line for the provided attribute and value. */ private String getLDIFLine(String attrName, ByteString value) { String v = value.toString(); if (isBinary(attrName) || Utilities.hasControlCharaters(v)) { // To indicate that is base64 encoded return attrName + ":: " + value.toBase64String(); } return attrName + ": " + v; } }